rust - 将不可复制的拥有值传递给函数后尝试使用它们时会出现生命周期问题

标签 rust lifetime ownership

我在 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 in do_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/

相关文章:

memory - 如何确定Rust中的new()何时在堆栈或堆上进行分配

rust - 交换两个本地引用会导致生命周期错误

rust - 将所有权移至 std::io::Chain

rust - <T : Trait> Box<T> and &Trait/Box<Trait>? 有什么区别

rust - 什么时候静态生命周期不合适?

rust - 为什么链接生存期仅与可变引用有关?

rust - 使用迭代器作为来自一个向量的函数的参数多次

c++ - 如何在 Windows 中更改文件的所有权

rust - CSV from_writer 在 stdout() 上工作,但在 from_path 上失败

c++ - 无法成功返回我通过在字符串上调用 c_str() 创建的 const char*。 (C++)