在将它们传递给函数后尝试使用它们时,不可复制的拥有值的生命周期问题
Lifetime issues with non-copyable owned values when trying to use them after passing them to a function
我 运行 遇到了 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
我认为 Option<NonCopyable>
只是 try_wrap
的错误 return 类型。你需要一个像Result
这样的双臂求和类型,这样调用者可以在出错的情况下恢复参数,可能像这样:
fn do_stuff() -> NonCopyable {
let x = NonCopyable::new();
match try_wrap(x) {
Ok(val) => val,
Err(x) => x,
}
}
fn try_wrap(x: NonCopyable) -> Result<NonCopyable, NonCopyable> {
Err(x)
}
with lifetime of variables
这里不涉及生命周期
The x
variable in do_stuff
is borrowed
不,不是。
Am I thinking about this the wrong way?
是的。借用符号 &
and/or 生命周期参数 '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
,您可以显式调用 [=25] =] 在 try_wrap
的参数上,以保持本地值。
如 notes, you can use a type to return either the wrapped value or the original. It's difficult to tell based on your example, but I disagree with using Result
unless it's an error. Instead, I'd create my own one-off enum or use something like 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 中变量生命周期的一些问题。 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
我认为 Option<NonCopyable>
只是 try_wrap
的错误 return 类型。你需要一个像Result
这样的双臂求和类型,这样调用者可以在出错的情况下恢复参数,可能像这样:
fn do_stuff() -> NonCopyable {
let x = NonCopyable::new();
match try_wrap(x) {
Ok(val) => val,
Err(x) => x,
}
}
fn try_wrap(x: NonCopyable) -> Result<NonCopyable, NonCopyable> {
Err(x)
}
with lifetime of variables
这里不涉及生命周期
The
x
variable indo_stuff
is borrowed
不,不是。
Am I thinking about this the wrong way?
是的。借用符号 &
and/or 生命周期参数 '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
,您可以显式调用 [=25] =] 在 try_wrap
的参数上,以保持本地值。
如Result
unless it's an error. Instead, I'd create my own one-off enum or use something like 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) {}