rust – 尝试使用std :: util :: replace时的借用问题

use std::util::replace;

假设我们有这些结构:

struct Foo {
    a: ~[Baz],
}

struct Bar {
    a: ~[Quux],
}

struct Baz {
    x: bool
}

struct Quux {
    x: bool,
    y: Bar,
}

以下工作正常:

    let mut foo = Foo{a: ~[Baz {x: true},
                           Baz {x: false}]};

    println!("{}, {}", foo.a[0].x, foo.a[1].x); // true false
    replace(&mut foo.a[0], foo.a[1]);
    println!("{}, {}", foo.a[0].x, foo.a[1].x); // false false

但是,这不起作用:

    let mut bar = Bar{a: ~[Quux {x: true, y: Bar {a: ~[]} },
                           Quux {x: false, y: Bar {a: ~[]} }]
    };

    println!("{}, {}", bar.a[0].x, bar.a[1].x); // true false

    replace(&mut bar.a[0], bar.a[1]);
}

编译器给出的错误是:

foobar_borrow2.rs:35:28: 35:36 error: cannot move out of `(*bar.a)[]` because it is borrowed
foobar_borrow2.rs:35     replace(&mut bar.a[0], bar.a[1]);
                                                ^~~~~~~~
foobar_borrow2.rs:35:13: 35:26 note: borrow of `(*bar.a)[]` occurs here
foobar_borrow2.rs:35     replace(&mut bar.a[0], bar.a[1]);
                                 ^~~~~~~~~~~~~

我不明白这意味着什么.这看起来类似于之前的情况,它起作用.为什么在Quux中添加Bar字段会导致它失败?

最佳答案 我想我现在明白了,但首先我认为简化是值得的.让我们将Quux改为:

struct Quux {
        x: ~bool,
}

这会导致相同的错误.回想一下,Foo.a是Baz的独特载体. Baz具有复制语义,因为它是一个结构,其字段都具有复制语义(即单个int字段).因此将foo.a [1]传递给replace的第二个参数会导致其值被复制.

另一方面,Bar.a是Quux的独特载体. Quux具有移动语义,因为它的唯一字段是一个指向布尔值的拥有指针.因此,当我们通过bar.a [1]进行替换时,它会尝试移动向量bar.a的所有权来替换.但我们不能这样做,因为(显然?)在第一个替换参数中使用bar.a [0]的可变借用导致整个向量已被借用.

在这个简单的例子中我们可以看到关于向量的最后一个事实

let mut x = ~[1, 5, 9];
let y = &mut x[0];
let z = &x[1]; //error: cannot borrow (*x)[] as immutable because it is already borrowed as mutable

在我的原始示例中,Quux具有移动语义,因为它具有Bar字段,并且Bar具有移动语义,因为它具有向量作为其字段之一.所以相同的原则在起作用.

点赞