gpt4 book ai didi

rust - 在涉及线和 map 的情况下对所有权感到困惑

转载 作者:行者123 更新时间:2023-12-03 11:27:34 25 4
gpt4 key购买 nike

fn problem() -> Vec<&'static str> {
let my_string = String::from("First Line\nSecond Line");
my_string.lines().collect()
}

这会因编译错误而失败:

  |
7 | my_string.lines().collect()
| ---------^^^^^^^^^^^^^^^^^^
| |
| returns a value referencing data owned by the current function
| `my_string` is borrowed here

我了解此错误的含义 - 它是为了阻止您返回对超出范围的值的引用。查看所涉及函数的类型签名后,问题似乎出在 lines 上。方法,它借用了调用它的字符串。但为什么这很重要?我正在遍历字符串的行以获得部分的向量,我返回的是这个"new"向量,而不是任何会(非法)直接引用 my_string .

(我知道我可以很容易地修复这个特定的例子,只需使用字符串文字,而不是使用 String::from 转换为“拥有”字符串。这是一个玩具示例重现问题 - 在我的“真实”代码中,字符串变量是从文件中读取的,所以我显然不能使用文字。)

对我来说更神秘的是,对我来说应该遇到同样问题的函数的以下变体可以正常工作:

fn this_is_ok() -> Vec<i32> {
let my_string = String::from("1\n2\n3\n4");
my_string.lines().map(|n| n.parse().unwrap()).collect()
}

原因不能是 map 做了一些魔术,因为这也失败了:

fn also_fails() -> Vec<&'static str> {
let my_string = String::from("First Line\nSecond Line");
my_string.lines().map(|s| s).collect()
}

我已经玩了很长一段时间,尝试了 map 中的各种不同功能 - 有些通过,有些失败,老实说,我不知道有什么区别。所有这一切都让我意识到我对 Rust 的所有权/借用规则如何在不平凡的情况下工作知之甚少,尽管我认为我至少了解了基础知识。因此,如果有人能给我一个相对清晰和全面的指南,了解所有这些示例中发生了什么,以及如何以某种直接的方式修复那些失败的示例,我将非常感激!

最佳答案

键是 lines 产生的值的类型: &str .为了避免不必要的克隆,lines实际上返回对调用它的字符串切片的引用,并且当您将其收集到 Vec 时, 那 Vec的元素只是对字符串切片的引用。因此,当然,当您的函数退出并删除字符串时,Vec 中的引用将被丢弃且无效。请记住,&str是借来的字符串,String是一个拥有的字符串。

解析有效,因为您采用了 &str s 然后你把它们读成 i32 ,因此数据被转移到一个新值,您不再需要对原始字符串的引用。

要解决您的问题,只需使用 str::to_owned将每个元素转换为 String :

fn problem() -> Vec<String> {
let my_string = String::from("First Line\nSecond Line");
my_string.lines().map(|v| v.to_owned()).collect()
}

需要注意的是to_string也有效,那to_owned实际上是 ToOwned 的一部分trait,因此它对其他借用的类型也很有用。

对于大小值的引用(str 未调整大小,因此不适用),例如 Iterator<Item = &i32> ,您可以简单地使用 Iterator::cloned 克隆每个元素,使它们不再是引用。

另一种解决方案是采用 String作为参数,因此它以及对它的引用可以超出函数的范围:

fn problem(my_string: &str) -> Vec<&str> {
my_string.lines().collect()
}

关于rust - 在涉及线和 map 的情况下对所有权感到困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65116716/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com