向Rust中的HashSet添加值,并向另一个数据结构添加对它的引用

sg3maiej  于 2022-12-04  发布在  其他
关注(0)|答案(2)|浏览(136)

我尝试从一个函数返回一个Vector。这发生在一个循环中,我需要值存在于循环之外。由于我多次执行返回,我只需要唯一的值,我想我使用了一个HashSet,我在其中插入,然后尝试获得对下一行中的值的引用。
我需要在多个其他数据结构中引用该值,但不想复制实际值。值不需要是可变的。

我所尝试的#

use std::collections::HashSet;
fn main() {
    let mut vec: Vec<&str> = Vec::new();

    let mut books = HashSet::new();
    for i in 0..5 {
        // This could be a function call, which returns a vector of objects, which should all be
        // stored centrally and uniquely in a HashSet
        books.insert("A Dance With Dragons".to_string());

        let mut reference: &str = books.get("A Dance With Dragons").unwrap();
        // This would be done for multiple "refering" datastructures
        vec.push(reference);
    }
}

我所期待的
获取指向HashSet中字符串的指针以供将来使用。

事实上发生了什么

error[E0502]: cannot borrow `books` as mutable because it is also borrowed as immutable
  --> src/main.rs:10:9
   |
10 |         books.insert("A Dance With Dragons".to_string());
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here
11 |
12 |         let mut reference: &str = books.get("A Dance With Dragons").unwrap();
   |                                   --------------------------------- immutable borrow occurs here
13 |         // This would be done for multiple "refering" datastructures
14 |         vec.push(reference);
   |         ------------------- immutable borrow later used here

For more information about this error, try `rustc --explain E0502`.
warning: `set_test` (bin "set_test") generated 2 warnings
error: could not compile `set_test` due to previous error; 2 warnings emitted

我想我错过了一个非常明显的解决方案...
提前感谢您的帮助。

qlvxas9a

qlvxas9a1#

你不能这么做

use std::collections::HashSet;
fn main() {
    let mut v: Vec<&str> = Vec::new();

    let mut books = HashSet::new();
    for i in 0..5 {
        // this needs to borrow mutably
        books.insert("A Dance With Dragons".to_string());

        // this reference has to live as long as v
        // so on the second iteration books is still borrowed
        // which means you can't borrow it mutably any more.
        let reference: &str = books.get("A Dance With Dragons").unwrap();
        v.push(reference);
    }

    // v only goes out of scope here
}

你可能会发现分离突变和引用是成功的,就像这样:

fn main() {
    let mut books = HashSet::new();
    for i in 0..5 {
        books.insert("A Dance With Dragons".to_string());
    }

    let v: Vec<&str> = books.iter().collect();
}

或者像pigeonhdandan建议的那样使用Rc

fn main() {
    let mut v: Vec<Rc<str>> = Vec::new();

    let mut books = HashSet::new();
    for i in 0..5 {
        books.insert(Rc::new("A Dance With Dragons".to_string()));

        // note: this clone is cheap cause it only clones the `Rc` not the whole String.
        let reference = books.get("A Dance With Dragons").unwrap().clone();
        v.push(reference);
    }
}
z31licg0

z31licg02#

问题是“book”中的值可能会被删除,而你试图在一个向量中保存引用。这是一个空指针的风险。
您需要以一种可变方式来构建这本书,就像这样

use std::collections::HashSet;

fn main() {
    let mut vec: Vec<&str> = Vec::new();
    
    let books: HashSet<String> = vec!(
        "A Dance With Dragons".to_string(), 
        "A Dance With Dragons".to_string()).into_iter().collect();
        
    let reference: &str = books.get("A Dance With Dragons").unwrap();
     
    vec.push(reference);
}

相关问题