在我克隆它之前,Vector 的寿命不够长
Vector doesn't live long enough until I clone it
我不明白为什么 v
在代码段 (2)
中的寿命不够长,但它在其他情况下有效。如果我不需要 clone
(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
消耗 选项和 returns Vec
,其所有权传递给变量 v
。对 last
return 的调用是对 v
.
的引用
在第二种情况下,Option
的所有权从 make_vec
转移到对 and_then
的调用。 and_then
消耗 Option
,并将 Vec
的所有权传递给闭包。在闭包 return 中对 last
的调用是对 Vec
的引用。由于闭包拥有向量但现在已完成 运行,因此 Vec
将被删除。对 Vec
的引用将指向不再有效的内存,因此会出现编译错误。
在第三种情况下,Option
的所有权从 make_vec
转移到对 and_then
的调用。 and_then
消耗 Option
,并将 Vec
的所有权传递给闭包。在闭包 return 中对 last
的调用是对 Vec
的引用。 referred-to 项目被克隆,创建一个不同于 Vec
的新项目。当 Vec
在关闭后被删除时,没有对它的引用可能会导致问题。
m
的类型因您的案例而异。如果第一种和第二种情况都有效,它们将是 return 和 Option<&u32>
。第三种情况 returns a Option<u32>
.
还有第四个选项:
let r = make_vec();
let m = r.as_ref().and_then(|v| v.last());
这会将 Option<T>
转换为 Option<&T>
。这个新的 Option
引用 原始 选项,可以通过调用 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.
优化是一件棘手的事情,唯一正确的答案是查看优化后的输出。 I 会假设任何 Copy
和 "small enough" 都不会真正引起问题。但是,我可能会考虑让我的代码尽可能语义化,以帮助优化器。如果该代码是您的意思,我可能会尝试使用 pop
变体。
我不明白为什么 v
在代码段 (2)
中的寿命不够长,但它在其他情况下有效。如果我不需要 clone
(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
消耗 选项和 returns Vec
,其所有权传递给变量 v
。对 last
return 的调用是对 v
.
在第二种情况下,Option
的所有权从 make_vec
转移到对 and_then
的调用。 and_then
消耗 Option
,并将 Vec
的所有权传递给闭包。在闭包 return 中对 last
的调用是对 Vec
的引用。由于闭包拥有向量但现在已完成 运行,因此 Vec
将被删除。对 Vec
的引用将指向不再有效的内存,因此会出现编译错误。
在第三种情况下,Option
的所有权从 make_vec
转移到对 and_then
的调用。 and_then
消耗 Option
,并将 Vec
的所有权传递给闭包。在闭包 return 中对 last
的调用是对 Vec
的引用。 referred-to 项目被克隆,创建一个不同于 Vec
的新项目。当 Vec
在关闭后被删除时,没有对它的引用可能会导致问题。
m
的类型因您的案例而异。如果第一种和第二种情况都有效,它们将是 return 和 Option<&u32>
。第三种情况 returns a Option<u32>
.
还有第四个选项:
let r = make_vec();
let m = r.as_ref().and_then(|v| v.last());
这会将 Option<T>
转换为 Option<&T>
。这个新的 Option
引用 原始 选项,可以通过调用 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.
优化是一件棘手的事情,唯一正确的答案是查看优化后的输出。 I 会假设任何 Copy
和 "small enough" 都不会真正引起问题。但是,我可能会考虑让我的代码尽可能语义化,以帮助优化器。如果该代码是您的意思,我可能会尝试使用 pop
变体。