首页 文章

移动可变借入的所有权

提问于
浏览
5

我的理解是,可变借款人可以将所有权转移给另一个可变借款人 . 但这一举动似乎与移动非指针变量有点不同 . 我们来看一个例子吧 . 当 compute() 第一次被调用时, p1 以下被移动到 p2 . 但在 compute() 回归之后,所有权似乎又回到了 p1 .

fn compute(p2: &mut Point) {
}

fn reset(p1: &mut Point) {
    compute(p1); //OK
    compute(p1); //OK
}

这与常规变量的移动方式不同 .

fn compute(p2:  Point) {
}

fn reset(p1: Point) {
    compute(p1); //OK
    compute(p1); //Compile error
}

现在,在第一次 compute() 调用返回后,所有权不会恢复为 p1 .

出于多种原因,这两种行为都是可以理解和可取的但我只想证实我的理解,这两个举动在性质上略有不同 . 我是这样思考的吗?

3 回答

  • 2

    我理解的方式是你的第一个片段借用,第二个片段转移所有权 .

    fn compute(p2:  Point) {
        // compute owns p2
    } // owned p2 is freed
    
    fn reset(p1: Point) {
        // reset() owns p1
        compute(p1); //Ownership of p1 is transferred to compute()
        compute(p1); //ERROR: p1 has already been freed
    }
    

    副...

    fn compute(p2:  &Point) {
        // compute is borrowing p2
    } // borrowed p2 is given back to owner
    
    fn reset(p1: Point) {
        // reset() owns p1
        compute(&p1); //let compute() borrow p1, then get it back
        compute(&p1); //let compute() re-borrow p1, then give it back
    } // owned p1 is freed
    
  • 0

    你是正确的,除了在第一个例子中,引用没有被移动,它只是被重新借用,这是引用特有的行为 . 也许这会清除它,因为它在移动语义中不是例外,而是完全不同的行为 .

  • 2

    另外两个答案是正确的,但我想强调Rust中的两个重点:

    • 第一点是关于Rust中的 default behaviour :当你将一个非引用对象传递给一个函数时,它会被移动到函数( by default! ) . 也就是说,该函数获取对象的所有权,并且一旦函数返回,调用者就不能再使用该对象 . 这就是你的第二个例子中发生的事情 - 因为第一次调用 compute 取得了传递的参数的所有权,你不能在下次调用 compute 时传递相同的对象,因为它已被移动 .

    • 如果您不想要默认行为,那么您必须通过声明您希望将(非参考对象的)副本传递给该函数来指示编译器您想要的内容 . 对于更简单的情况,这很容易 - 只需为您的结构派生 CloneCopy .

    #[derive(Clone, Copy)]  # instruction for the compiler!
    struct Point {
        x: i32,
        y: i32,
    }
    

    如果您像这样定义 Point ,那么即使您的第二个代码也可以正常编译 . 了解它在playground中的工作原理 . 我想this就是你如何定义你的 Point .

相关问题