rust - Rust 时间线和所有权问题

标签 rust lifetime ownership

我正在尝试通过读取文件来创建 HashMap 。下面是我写的代码。不同之处在于,我需要将 subset_description 保留到下一次迭代,以便我可以将其存储在 hasmap 中,然后最终返回 hashmap。

fn myfunction(filename: &Path) -> io::Result<HashMap<&str, &str>> {
    let mut SIF = HashMap::new();
    let file = File::open(filename).unwrap();
    let mut subset_description = "";
    for line in BufReader::new(file).lines() {
        let thisline = line?;
        let line_split: Vec<&str> = thisline.split("=").collect();
        subset_description = if thisline.starts_with("a") {
            let subset_description = line_split[1].trim();
            subset_description
        } else {
            ""
        };
        let subset_ids = if thisline.starts_with("b") {
            let subset_ids = line_split[1].split(",");
            let subset_ids = subset_ids.map(|s| s.trim());
            subset_ids.collect()
        } else {
            Vec::new()
        };
        for k in subset_ids {
            SIF.insert(k, subset_description);
            println!("");
        }
        if thisline.starts_with("!dataset_table_begin") {
            break;
        }
    }
    Ok(SIF)
}

我收到以下错误,无法解决此问题

error[E0515]: cannot return value referencing local variable `thisline`
  --> src/main.rs:73:5
   |
51 |         let line_split: Vec<&str> = thisline.split("=").collect();
   |                                     -------- `thisline` is borrowed here
...
73 |     Ok(SIF)
   |     ^^^^^^^ returns a value referencing data owned by the current function

最佳答案

问题在于 Rust 代表您做出的保证。问题的根源如下所示。您正在读取一个文件并将其内容处理到 HashMap 中,并且您正试图返回对您读取的数据的引用。但是通过返回一个引用,您需要保证文件中的字符串以后不会被更改,而您自然不能这样做。

在 Rust 术语中,您不断尝试返回对局部变量的引用,这些引用在函数末尾被丢弃,这将有效地为您留下悬空指针。这是我所做的更改,尽管它们可能不是最有效的,但它们确实可以编译。

fn myfunction(filename: &Path) -> io::Result<HashMap<String, String>> {
    let mut SIF = HashMap::new();
    let file = File::open(filename).unwrap();
    let mut subset_description = "";
    for line in BufReader::new(file).lines() {
        let thisline = line?;
        let line_split: Vec<String> = thisline.split("=").map(|s| s.to_string()).collect();
        subset_description = if thisline.starts_with("a") {
            let subset_description = line_split[1].trim();
            subset_description
        } else {
            ""
        };
        let subset_ids = if thisline.starts_with("b") {
            let subset_ids = line_split[1].split(",");
            let subset_ids = subset_ids.map(|s| s.trim());
            subset_ids.map(|s| s.to_string()).collect()
        } else {
            Vec::new()
        };
        for k in subset_ids {
            SIF.insert(k, subset_description.to_string());
            println!("");
        }
        if thisline.starts_with("!dataset_table_begin") {
            break;
        }
    }
    Ok(SIF)
}

如您所见,现在您放弃了返回值中字符串的所有权。这是通过修改返回类型并使用 to_string() 函数来实现的,将本地字符串的所有权交给 HashMap

有一种说法认为 to_string() 很慢,因此您可以探索 into 或 to_owned() 的使用,但由于我不精通这些构造我不能帮你优化。

关于rust - Rust 时间线和所有权问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56306074/

相关文章:

rust - Rust 中函数引用的生命周期

Rust:我可以通过以简单的方式在较小的范围内借用整个固定大小的数组来获得固定大小的切片吗

rust - 是否有任何机制可以使用 Rust 或 Rust 工具生成 "ownership tree"可视化?

rust - 结果<T, E> 输入 Rust。为什么引用不能作为 T 或 E 传递?

rust - 为什么 "one type is more general than the other"在包含闭包的选项中?

rust - Send 和 'static on a closure in rust 有什么区别?

rust - 如何忽略序列的部分项

rust - 修改 HashMap 对象中的特定值,以防以后可以移动其对象的所有权

rust - 有没有办法在 Option 中拆分变量而不必使用 if 语句?

rust - 变量具有不同的生命周期,而它们本应具有相同的生命周期