【发布时间】:2019-10-27 16:12:28
【问题描述】:
我正在编写 Rust Book(第 4 章),我很惊讶像这样的代码 compiles:
fn main() {
let mut s = String::from("hello");
let r1 = &s;
let r2 = &s;
println!("{}, {}", r1, r2);
// this line silences the warning: 'variable does not need to be mutable'
s.push_str(" world");
}
为什么 Rust 允许对可变变量进行不可变引用?这似乎会削弱安全保障。如果我有一个可变变量,并且我将不可变引用传递给某些线程,那么这些线程会假设该值不会改变,但我可以通过原始变量改变该值。
我还没有达到线程,但发现这很奇怪,在这种情况下,与 C++ 没有什么不同:
void doNotChangeMyString(const std::string& myConstString) {
// ... assume that myConstString cannot change and use it on a thread
// return immediately even though some worker thread is still
// using myConstString
}
void main() {
std::string s = "hello" // not const!
doNotChangeMyString(s);
s = "world"; // oops
}
编辑:我修复了 Rust 代码,以便它可以编译。请重新考虑反对票并关闭投票。接受的答案解释了一个我没有从 Rust Book 的借用章节中得到的概念,对我非常有帮助,并且可以帮助其他在学习 Rust 方面处于同一点的人。
【问题讨论】:
-
尝试真正编写您所暗示的代码。你会发现你无法编译它。
-
你是说 Rust 版本?这可能是答案,即我在书中还没有走得足够远。
-
为了清楚起见,您实际发布的 Rust 代码也无法编译,因此您假设 Rust 允许它是错误的。这就是为什么在本书中它被印成粉红色背景和一只迷惑的螃蟹:为了说明这是无法编译的代码。
-
我发布的 Rust 代码中的可变借用不是说明问题所必需的,你是对的,这是一个编译错误。我从示例代码中删除了可变借用,这应该可以改善问题。 @Optimistic Peach 解释的我不知道的概念是,如果原始变量已发生突变,编译器将阻止我使用不可变引用。我不认为这在 The Rust Book 第 4 章中有解释。
-
“如果原始变量已发生变异,编译器将阻止我使用不可变引用”,不完全是,您读错了。 NLL(非词法生命周期)允许缩短对象的生命周期,直到其最后一次使用不同于,如果它指向的值发生突变,则不允许使用它。当您改变值时,编译器会简单地删除共享引用。编译器阻止的是当存在对它的实时(非隐式删除)共享引用时值的突变。
标签: rust