在下面的例子中,为什么 B
的 get_foos_mut
的实现给出了生命周期错误,而 get_foos
的实现工作正常?
trait Foo {
fn get_foos<'a>(&'a self) -> Vec<&'a Foo> { Vec::new() }
fn get_foos_mut<'a>(&'a mut self) -> Vec<&'a mut Foo> { Vec::new() }
fn hello(&self) { println!("Hello!") }
}
struct A { i: int }
impl Foo for A { fn hello(&self) { println!("Hello {}!", self.i) } }
struct B { foos: Vec<A> }
impl Foo for B {
fn get_foos<'a>(&'a self) -> Vec<&'a Foo> {
Vec::from_fn(self.foos.len(), |i| self.foos.get(i) as &Foo) // This is fine.
}
fn get_foos_mut<'a>(&'a mut self) -> Vec<&'a mut Foo> {
Vec::from_fn(self.foos.len(), |i| self.foos.get_mut(i) as &mut Foo) // This gives an error?
}
}
fn main() {
let b = B { foos: vec![A { i: 1 }] };
for foo in b.get_foos().iter() {
foo.hello();
}
}
这是围栏给出的错误:
<anon>:17:43: 17:52 error: lifetime of `self` is too short to guarantee its contents can be safely reborrowed
<anon>:17 Vec::from_fn(self.foos.len(), |i| self.foos.get_mut(i) as &mut Foo)
^~~~~~~~~
<anon>:16:59: 18:6 note: `self` would have to be valid for the lifetime 'a as defined on the block at 16:58...
<anon>:16 fn get_foos_mut<'a>(&'a mut self) -> Vec<&'a mut Foo> {
<anon>:17 Vec::from_fn(self.foos.len(), |i| self.foos.get_mut(i) as &mut Foo)
<anon>:18 }
<anon>:17:9: 17:76 note: ...but `self` is only valid for the call at 17:8
<anon>:17 Vec::from_fn(self.foos.len(), |i| self.foos.get_mut(i) as &mut Foo)
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to previous error
playpen: application terminated with error code 101
注意:我注意到 B
的 get_foos_mut
如果这样写就可以工作:
fn get_foos_mut<'a>(&'a mut self) -> Vec<&'a mut Foo> {
let mut vec: Vec<&'a mut Foo> = Vec::with_capacity(self.foos.len());
for foo in self.foos.mut_iter() { vec.push(foo); }
vec
}
为什么实现在这种情况下有效,而不是在上面的 Vec::from_fn(...)
版本中?
最佳答案
&mut
指针必须是无别名的,也就是说,如果您想通过 进行变异,则不能有其他引用/指针/路径可以用来读取/写入数据&mut
。当您调用 self.foos.get_mut(i)
时,get_mut
对编译器来说就像一个黑匣子,它无法判断借用了哪些数据,因此它由于签名(通过生命周期将返回值连接到 self
对象),必须假设整个 Vec
是借用的
fn get_mut<'a>(&'a mut self, index: uint) -> &'a mut T
否则有人可以制作别名 &mut
指针:例如
let a = self.foos.get_mut(0);
let b = self.foos.get_mut(0);
The mut_iter
implementation内部使用了unsafe
,但是仔细写了一个安全的接口(interface),就是没有办法使用mut_iter
来获取aliasing &mut
指针(没有 unsafe
),因为它按顺序只产生每个可变引用一次。
FWIW,我会将这些方法写成 self.foos.iter().map(|x| x as &Foo).collect()
和 self.foos.mut_iter() .map(|x| x as &mut Foo).collect()
而不是显式的 push
或 from_fn
关于immutability - 在以下方法实现中,可变性如何影响 `self` 的生命周期?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24750369/