try*_*lly 1 struct mutability rust borrow-checker
我仍然很难理解为什么&mut self需要修改我的结构所拥有的对象的内部状态。我明白为什么我必须使用至少&self,因为我不想消费self,结束它的存在。我也明白为什么我必须使用&mut self如果我修改结构的字段,但我不这样做。
我有以下结构和实现:
\nstruct Writer {\n obj: json::JsonValue\n}\n\nimpl<\'b> Writer {\n fn from(obj: json::JsonValue) -> Self {\n Self {\n obj\n }\n }\n\n fn put(&mut self, field_name: &str, value: bool) {\n self.obj.insert(field_name, value);\n // ^^^- not modifying this, but a field inside "obj"\n }\n\n fn release_ownership(self) -> json::JsonValue {\n self.obj\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n用法:
\nwriter.put(field_name, true);\nRun Code Online (Sandbox Code Playgroud)\n使用&self而不是&mut self我会得到一个编译器错误:
`^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be borrowed as mutable`\nRun Code Online (Sandbox Code Playgroud)\nRust书教会了我:
\n\n\n如果我们想更改我们\xe2\x80\x99调用该方法的实例作为该方法的一部分,我们\xe2\x80\x99d使用 &mut self 作为第一个参数。
\n
我不明白如何修改这里的结构。我明确修改了struct 中的字段(此处obj),但没有修改结构本身。
在我可以看到的定义JsonValue::insert()&mut self中,我也不理解,因为它“仅”改变了through的内容。objectJsonValue::Object::insert()
Rust书中说:
\n\n\n请注意,整个实例必须是可变的;Rust 不允许我们仅将某些字段标记为可变。
\n
如果我想修改字段值,我可以理解这一点,但如果字段是指向已修改的其他结构的指针,我就不能理解这一点。
\n我的直觉告诉我,我限定的 with&mut不是指对数据的直接引用,而是指沿着所有指针的整个路径或最终引用。如果是这样的话:为什么会这样?
然而,这似乎是多余的,因为JsonValue::insert()已经强制对其内部对象进行可变访问。因此编译器知道, 的实例JsonValue是可变借用的用于插入,并且不能再次借用,直到它被释放。
作业:阅读这本书并进行搜索。
\n访问链上的所有内容都必须声明为可变引用,以确保无法获得对同一对象的两个可变引用。考虑一下:
struct ContainsMutable<'a>(&'a mut i8);
fn main() {
let mut a = 99;
let cm = ContainsMutable(&mut a);
let cmref1 = &cm;
let cmref2 = &cm;
// now if both references allowed mutable access to the pointee
// `a` we'd have a problem because this would be allowed
std::thread::scope(|s| {
s.spawn(|| {
*cmref1.0 = 55;
});
s.spawn(|| {
*cmref2.0 = 31;
});
});
}
Run Code Online (Sandbox Code Playgroud)
因此,我们永远不能允许对共享引用背后的某些内容(我们通过路径上某处的共享引用访问的内容)进行可变访问,因为我们可以轻松地以这种方式创建对同一对象的可变引用。
然而,这似乎是多余的,因为 JsonValue::insert() 已经强制对其内部对象进行可变访问。因此编译器知道,JsonValue 的实例是可变借用的用于插入,并且不能再次借用,直到它被释放。
假设编译器可以在编译时预测函数何时被调用并不允许这样做,但它不能,或者借用检查是在运行时完成的,但事实并非如此,借用检查是在编译时静态完成的。您可以使用RefCell,Mutex或进行运行时借用检查RwLock。
| 归档时间: |
|
| 查看次数: |
561 次 |
| 最近记录: |