rust - 如何在迭代器中使用字符串而不是 &str,if/else block

标签 rust

谁能给我解释一下为什么在此脚本中使用 String 不起作用,而 &str 却起作用。此外,我如何修改它以便它可以与 String 一起使用? [版本 1.2]

use std::collections::{HashMap};

fn main() { 

    let mut hash = HashMap::<&str, &str>::new();
    hash.insert("this", "value");
    let l: &str = "this is a borrowed string reference";
    // If the above line was defined as:
    //let l: String = "this is a string".to_string();

    let mut all = l.split(" ");   
    let name: &str = all.next().unwrap();

    if hash.contains_key(name) == true {
        hash.remove(name);
    } else {
        hash.insert(name, "stuff");
    }
}

最佳答案

好吧,让我们把它归结为必需品:

use std::collections::HashMap;

fn main() { 
    let mut hash = HashMap::<&str, &str>::new();
    hash.insert("this", "value");
    let l: String = "this is a borrowed string reference".to_string();
    hash.insert(&l, "stuff");
}

编译这个给我们:

<anon>:7:18: 7:19 error: `l` does not live long enough
<anon>:7     hash.insert(&l, "stuff");
                          ^
<anon>:4:49: 8:2 note: reference must be valid for the block suffix following statement 0 at 4:48...
<anon>:4     let mut hash = HashMap::<&str, &str>::new();
<anon>:5     hash.insert("this", "value");
<anon>:6     let l: String = "this is a borrowed string reference".to_string();
<anon>:7     hash.insert(&l, "stuff");
<anon>:8 }
<anon>:6:71: 8:2 note: ...but borrowed value is only valid for the block suffix following statement 2 at 6:70
<anon>:6     let l: String = "this is a borrowed string reference".to_string();
<anon>:7     hash.insert(&l, "stuff");
<anon>:8 }

这或多或少地告诉您确切什么是行不通的。您尝试将指向 String l 的借用指针插入 HashMap 中。然而,String 的生命周期不够长。

具体来说,Rust 以相反的词法顺序销毁值。因此,当执行到函数末尾时,Rust 将释放 l first,然后是 hash。这是一个问题:这意味着有一个窗口,在此期间 hash 包含指向已销毁数据的指针,这是 Rust 绝对不允许的。

这与 &str 一起工作的原因是字符串文字 "like this" 不仅仅是 &str;它实际上是 &'static str。这意味着字符串文字在整个程序运行期间都“存在”:它永远不会被销毁,因此 hashmap 保存指向它的指针是安全的。

解决方案是确保 String 的生命周期比 HashMap 长:

use std::collections::HashMap;

fn main() { 
    // Declare `l` here ...
    let l;
    let mut hash = HashMap::<&str, &str>::new();
    hash.insert("this", "value");

    // ... but initialise it *here*.
    l = "this is a borrowed string reference".to_string();
    hash.insert(&l, "stuff");
}

现在,hash 首先被销毁,然后是 l。保留一个未初始化的变量是可以的,只要您在读取或使用它之前对其进行初始化即可。

关于rust - 如何在迭代器中使用字符串而不是 &str,if/else block ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32119978/

相关文章:

rust - 是否有等同于 Haskell 在 Rust 中迭代的东西?

rust - 为什么我必须显式转换为受约束的类型?

rust - 为什么 `std::env::args` 返回 `String` 的迭代器而不是 `&' static str`?

multithreading - CPU 密集型工作线程的协作中断的习惯用法是什么?

rust - 在结构实现中使用不同的生命周期

rust - 删除 mut_iter 后在夜间构建中创建可变迭代器

rust - 自动解除引用和解除引用强制之间有什么关系?

collections - 在异构 Rust 集合中使用 Any trait 对象有什么问题?

rust - 使用包含借用参数的结构

rust - 当你借用一个临时的可窥视迭代器时会发生什么?