我的理解是,可变借款人可以将所有权转移给另一个可变借款人。但这一举动似乎与移动非指针变量有点不同。我们来看一个例子吧。第一次调用p1
时,p2
下方会移至compute()
。但在p1
返回后,所有权似乎又回到了compute()
。
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
}
现在,在第一次p1
调用返回后,所有权 不会恢复为compute()
。
出于多种原因,这两种行为都是可以理解和可取的。但我只想证实我的理解,这两个举动在本质上略有不同。我是这样思考的吗?
答案 0 :(得分:2)
你是正确的,除了在第一个例子中,引用没有被移动,它只是被重新借用,这是引用特有的行为。也许这会清除它,因为它在移动语义中不是例外,而是完全不同的行为。
答案 1 :(得分: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
答案 2 :(得分:0)
其他两个答案是正确的,但我想强调Rust中的两个要点:
第一点是关于Rust中的默认行为:当您将非引用对象传递给函数时,它将被移动到该函数(默认情况下为! / strong>)。也就是说,该函数获得对象的所有权,并且一旦函数返回,调用者就无法再使用该对象。那就是您第二个示例中发生的事情-因为对byte[] getBlobChunk(Connection connection, long lobId, long start, long chunkSize) throws SQLException {
Blob blob = PgBlob(connection, lobId);
InputStream is = blob.getBinaryStream(start, chunkSize);
return IOUtils.toByteArray(is);
}
的第一次调用获得了传递的参数的所有权,因此您无法在下一次对compute
的调用中传递同一对象,因为该对象已被移动。 / p>
如果您不想使用默认行为,则必须明确地通过告诉您想要(非引用对象的)副本来指示编译器所需的内容传递给函数。对于较简单的情况,这很容易-只需为您的结构派生compute
和Clone
。
Copy
如果您这样定义#[derive(Clone, Copy)] # instruction for the compiler!
struct Point {
x: i32,
y: i32,
}
,那么即使您的第二个代码也可以正常编译。在playground中查看其工作方式。我想this是您定义Point
的方式。