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]);
^~~~~~~~~~~~~
我不明白这意味着什么 . 这似乎与之前的案例类似,但是有效 . 为什么将 Bar
字段添加到 Quux
导致它失败?
2 回答
我想我现在明白了,但首先我认为's worthwhile to simplify. Let'将_1275350改为:
这会导致相同的错误 . 回想一下
Foo.a
是Baz
的唯一向量 .Baz
具有复制语义,因为它是一个结构,其字段都具有复制语义(即单个int
字段) . 因此,将foo.a[1]
传递给replace
的第二个参数会导致其值被复制 .另一方面,
Bar.a
是Quux
的唯一向量 .Quux
具有移动语义,因为它的唯一字段是指向布尔值的拥有指针 . 因此,当我们将bar.a[1]
传递给replace
时,它会尝试将向量bar.a
的所有权移至replace
. 但我们不能这样做,因为(显然?)在replace
的第一个参数中采用bar.a[0]
的可变借用导致整个向量已被借用 .在这个简单的例子中我们可以看到关于向量的最后一个事实
在我的原始示例中,
Quux
具有移动语义,因为它具有Bar
字段,并且Bar
具有移动语义,因为它具有向量作为其字段之一 . 所以相同的原则在起作用 .这里替换函数获取借用
bar
的所有权,当编译器到达第一次使用bar时,这是bar.a[0]
:replace(&mut bar.a[0], bar.a[1]);
在此之后,在函数完成之前,编译器会阻止进一步使用
bar
. 不幸的是,这会阻止函数的第二个参数被接受,因为它是在此刻采取的 .另一种方法是将
bar.a[1]
的内容复制到一个新变量中,并将此新变量作为第二个参数发送到replace()
:这会将bar.a [1]中的值复制到新变量中 .
这将需要bar及其内容来实现特征
std::clone::Clone
. 对于此示例,将#[deriving(Clone]
添加到Bar和Quuz将起作用 .