我的理解是,可变借款人可以将所有权转移给另一个可变借款人 . 但这一举动似乎与移动非指针变量有点不同 . 我们来看一个例子吧 . 当 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 回答
我理解的方式是你的第一个片段借用,第二个片段转移所有权 .
副...
你是正确的,除了在第一个例子中,引用没有被移动,它只是被重新借用,这是引用特有的行为 . 也许这会清除它,因为它在移动语义中不是例外,而是完全不同的行为 .
另外两个答案是正确的,但我想强调Rust中的两个重点:
第一点是关于Rust中的 default behaviour :当你将一个非引用对象传递给一个函数时,它会被移动到函数( by default! ) . 也就是说,该函数获取对象的所有权,并且一旦函数返回,调用者就不能再使用该对象 . 这就是你的第二个例子中发生的事情 - 因为第一次调用
compute
取得了传递的参数的所有权,你不能在下次调用compute
时传递相同的对象,因为它已被移动 .如果您不想要默认行为,那么您必须通过声明您希望将(非参考对象的)副本传递给该函数来指示编译器您想要的内容 . 对于更简单的情况,这很容易 - 只需为您的结构派生
Clone
和Copy
.如果您像这样定义
Point
,那么即使您的第二个代码也可以正常编译 . 了解它在playground中的工作原理 . 我想this就是你如何定义你的Point
.