我不明白为什么 v
在片段 (2)
中的生命周期不够长,但它在其他情况下有效。如果我不需要克隆
(1)
中的变量,为什么我需要克隆它才能使第二种情况起作用?
fn main() {
// (1)
let v = make_vec().unwrap();
let m = v.last();
// (2) v doesn't live long enough!
let m = make_vec()
.and_then(|v| v.last());
// (3) Fixed!
let m = make_vec()
.and_then(|v| v.last().cloned());
}
fn make_vec() -> Option<Vec<u32>> {
Some(vec![1, 2, 3])
}
最佳答案
在第一种情况下,Option
的所有权从 make_vec
传递到 unwrap
称呼。 unwrap
消费 Option 并返回 Vec
,其所有权传递给变量 v
.调用last
返回对 v
的引用.
在第二种情况下,Option
的所有权从 make_vec
传递调用and_then
. and_then
消耗 Option
, 并传递 Vec
的所有权到关闭。调用last
在闭包中返回对 Vec
的引用.由于闭包拥有向量但现在已完成运行,Vec
将被丢弃。引用到Vec
将指向不再有效的内存,因此会出现编译错误。
在第三种情况下,Option
的所有权从 make_vec
传递调用and_then
. and_then
消耗 Option
, 并传递 Vec
的所有权到关闭。调用last
在闭包中返回对 Vec
的引用.引用的项目被克隆,这将创建一个不同于 Vec
的新项目.当 Vec
在关闭后被丢弃,没有可能导致问题的引用。
m
的类型你的情况不同。第一种和第二种情况将返回 Option<&u32>
。如果他们都工作。第三种情况返回 Option<u32>
.
还有第四种选择:
let r = make_vec();
let m = r.as_ref().and_then(|v| v.last());
这会转换 Option<T>
进入 Option<&T>
.这个新Option
引用 original 选项,可以通过调用 and_then
使用.
还有第五种选择! ^_^ 如果你只是打算扔掉向量,你可以更明确地说明你无论如何都想接受它:
let m = make_vec().and_then(|v| v.pop());
Does clone here actually copy things in memory or will the compiler optimise it to effectively pass the ownership of the vector element back? Since this was u32s throughout, I was expecting that they would generally be copied instead of referenced.
优化是一件棘手的事情,唯一真正的答案是查看优化后的输出。 我会假设任何Copy
并且“足够小”不会真正造成问题。但是,我可能会考虑让我的代码尽可能语义化,以帮助优化器。我可能会尝试使用 pop
变体,如果该代码是你的意思。
关于rust - 在我克隆它之前,Vector 的生命周期不够长,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34535936/