gpt4 book ai didi

rust - 为什么允许在 &mut self 中借用结构成员,但不允许借用 self 到不可变方法?

转载 作者:行者123 更新时间:2023-11-29 07:46:27 25 4
gpt4 key购买 nike

如果我有一个封装两个成员的结构,并根据另一个成员更新一个,只要我这样做就没问题:

struct A {
value: i64
}

impl A {
pub fn new() -> Self {
A { value: 0 }
}
pub fn do_something(&mut self, other: &B) {
self.value += other.value;
}
pub fn value(&self) -> i64 {
self.value
}
}

struct B {
pub value: i64
}

struct State {
a: A,
b: B
}

impl State {
pub fn new() -> Self {
State {
a: A::new(),
b: B { value: 1 }
}
}
pub fn do_stuff(&mut self) -> i64 {
self.a.do_something(&self.b);
self.a.value()
}
pub fn get_b(&self) -> &B {
&self.b
}
}

fn main() {
let mut state = State::new();
println!("{}", state.do_stuff());
}

也就是我直接引用self.b的时候。但是当我将 do_stuff() 更改为:

pub fn do_stuff(&mut self) -> i64 {
self.a.do_something(self.get_b());
self.a.value()
}

编译器提示:不能将 `*self` 借用为不可变的,因为 `self.a` 也被借用为可变的

如果我需要做一些比返回成员更复杂的事情来获取 a.do_something() 的参数怎么办?我必须创建一个按值返回 b 的函数并将其存储在绑定(bind)中,然后将该绑定(bind)传递给 do_something() 吗?如果 b 很复杂怎么办?

对我来说更重要的是,编译器将我从这里拯救出来的是哪种内存不安全?

最佳答案

可变引用的一个关键方面是,当它们存在时,保证它们是访问特定值的唯一方式(除非它们被重新借用,这会暂时“禁用”它们)。

当你写作时

self.a.do_something(&self.b);

编译器能够看到对 self.a 的借用(隐式地执行方法调用)与对 self.b 的借用是不同的,因为它可以推理直接字段访问。

但是,当你写

self.a.do_something(self.get_b());

然后编译器看不到对self.b 的借用,而是对self 的借用。那是因为方法签名上的生命周期参数无法传播有关借用的此类详细信息。因此,编译器无法保证 self.get_b() 返回的值不会让您访问 self.a,这将创建两个可以访问 self.a,其中一个是可变的,这是非法的。

字段借用不跨函数传播的原因是为了简化类型检查和借用检查(对于机器人类)。原则是签名应该足以执行这些任务:更改函数的实现不应导致其调用者出错。

What if I need to do something more complex than just returning a member in order to get the argument for a.do_something()?

我会将 get_bState 移动到 B 并在 self.b< 上调用 get_b/。这样,编译器可以看到对 self.aself.b 的不同借用,并将接受代码。

self.a.do_something(self.b.get_b());

关于rust - 为什么允许在 &mut self 中借用结构成员,但不允许借用 self 到不可变方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42879098/

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