在第一种情况下,所有权Option
从make_vec
调用传递unwrap
。unwrap
使用Option并返回Vec
,其所有权传递给变量v
。调用last
返回对 的引用v
。
在第二种情况下,所有权Option
传递 frommake_vec
到调用 to and_then
。and_then
消耗,Option
并将所有权传递Vec
给闭包。闭包中的调用last
返回对Vec
. 由于闭包拥有该向量但现在已完成运行,因此Vec
将被删除。对 的引用Vec
将指向不再有效的内存,因此会出现编译错误。
在第三种情况下,所有权Option
传递 frommake_vec
到调用 to and_then
。and_then
消耗,Option
并将所有权传递Vec
给闭包。闭包中的调用last
返回对Vec
. 引用的项目被克隆,这会创建一个不同于Vec
. 在Vec
关闭后删除 时,没有可能导致问题的引用。
您的案例的类型m
不同。Option<&u32>
如果它们都有效,则第一种和第二种情况将返回 a 。第三种情况返回 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());
这里的克隆实际上是在内存中复制东西,还是编译器会对其进行优化以有效地将向量元素的所有权传回?由于自始至终都是 u32s,我希望它们通常会被复制而不是引用。
优化是一件棘手的事情,唯一真正的答案是查看优化后的输出。我会假设任何Copy
“足够小”的东西都不会真正引起问题。但是,我可能会考虑使我的代码尽可能语义化,以帮助优化器。pop
如果该代码是您的意思,我可能会尝试使用该变体。