我在 Rust 中的变量生命周期中遇到了一些问题。 do_stuff
中的 x
变量被借用给 try_wrap
,因此在 None
情况下无法返回。我是否以错误的方式思考这个问题?
struct NonCopyable;
impl NonCopyable {
fn new() -> Self {
NonCopyable
}
}
fn do_stuff() -> NonCopyable {
let x = NonCopyable::new();
match try_wrap(x) {
Some(val) => val,
None => x,
}
}
fn try_wrap(x: NonCopyable) -> Option<NonCopyable> {
None
}
fn main() {}
error[E0382]: use of moved value: `x`
--> src/main.rs:13:17
|
11 | match try_wrap(x) {
| - value moved here
12 | Some(val) => val,
13 | None => x,
| ^ value used here after move
|
= note: move occurs because `x` has type `NonCopyable`, which does not implement the `Copy` trait
最佳答案
with lifetime of variables
这里不涉及生命周期
The
x
variable indo_stuff
is borrowed
不,不是。
Am I thinking about this the wrong way?
是的。借用由 & 符号 &
和/或生命周期参数 'foo
表示:
&i32 // a borrowed integer
&'a str // a borrowed string slice with a lifetime
Foo<'b> // a type that contains a borrow of some kind
您的 try_wrap
函数取得 x
的所有权:
fn try_wrap(x: NonCopyable) -> Option<NonCopyable>
这意味着x
已经消失,调用函数无法再访问它。它已移动到try_wrap
,现在可以自由地对该值执行任何操作,包括销毁它。这就是为什么调用函数不再能够安全地访问它以及您收到错误的原因。
如果类型实现了Copy
,编译器将隐式创建该值的副本并将其传入。如果类型实现了Clone
,您可以显式地对 try_wrap
的参数调用 .clone()
以保留本地值。
如Florian Weimer请注意,您可以使用类型来返回包装值或原始值。根据您的示例很难判断,但我不同意使用 Result
除非它是一个错误。相反,我会创建自己的一次性枚举或使用类似 Either
的东西。 :
extern crate either;
use either::Either;
fn do_stuff() -> NonCopyable {
let x = NonCopyable::new();
match try_wrap(x) {
Either::Left(val) => val,
Either::Right(x) => x,
}
}
fn try_wrap(x: NonCopyable) -> Either<NonCopyable, NonCopyable> {
Either::Right(x)
}
您还可以将 try_wrap
的逻辑嵌入到 do_stuff
中,或者拆分 try_wrap
以便该逻辑不需要所有权:
fn do_stuff() -> NonCopyable {
let x = NonCopyable::new();
if should_wrap(&x) { do_wrap(x) } else { x }
}
fn should_wrap(x: &NonCopyable) -> bool { false }
fn do_wrap(x: NonCopyable) -> NonCopyable { x }
由于您返回相同的类型,因此您也可能希望获取对该值的可变引用,并执行需要发生的任何条件更改:
fn do_stuff() -> NonCopyable {
let mut x = NonCopyable::new();
try_wrap(&mut x);
x
}
fn try_wrap(x: &mut NonCopyable) {}
关于rust - 将不可复制的拥有值传递给函数后尝试使用它们时会出现生命周期问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45255478/