移动可变借入的所有权

时间:2014-12-25 19:38:40

标签: rust

我的理解是,可变借款人可以将所有权转移给另一个可变借款人。但这一举动似乎与移动非指针变量有点不同。我们来看一个例子吧。第一次调用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()

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

3 个答案:

答案 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>

  • 如果您不想使用默认行为,则必须明确地通过告诉您想要(非引用对象的)副本来指示编译器所需的内容传递给函数。对于较简单的情况,这很容易-只需为您的结构派生computeClone

    Copy

    如果您这样定义#[derive(Clone, Copy)] # instruction for the compiler! struct Point { x: i32, y: i32, } ,那么即使您的第二个代码也可以正常编译。在playground中查看其工作方式。我想this是您定义Point的方式。