gpt4 book ai didi

immutability - 在以下方法实现中,可变性如何影响 `self` 的生命周期?

转载 作者:行者123 更新时间:2023-11-29 08:13:05 26 4
gpt4 key购买 nike

在下面的例子中,为什么 Bget_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

注意:我注意到 Bget_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() 而不是显式的 pushfrom_fn

关于immutability - 在以下方法实现中,可变性如何影响 `self` 的生命周期?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24750369/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com