【问题标题】:Why does Rust allow upgrading/downgrading mutability?为什么 Rust 允许升级/降级可变性?
【发布时间】:2021-02-04 02:14:55
【问题描述】:

在 rust 中,您可以升级不可变变量:

let v = Vec::new(); // Immutable
let mut v = v;      // Mutable
v.push("hi");       // Succeeds

或者降级一个可变变量:

let mut v = Vec::new();   // Mutable
let v = v;                // Immutable
v.push("hi");             // Won't compile

我的问题是 - 为什么?

据我了解,用于存储变量值的底层内存永远不会是不可变的。从技术上讲,每个内存地址都可以写入。不变性是一种人为的约束,有人设置在我们身上(比如内核),或者我们设置在自己身上。

当我说:

let v = vec!["a", "b", "c"];

我是说我希望在内存中有一个具有这些值的变量,并且我不希望它以后被任何代码更改。如果我尝试在某个时候更改此变量,请给我一个错误。这是我定义的约束。

如果你以后可以这样做:

let mut v = v;

让它可变,然后改变它,这似乎违背了不可变变量的全部目的。那时,您不妨将所有变量设置为可变(就像在 Python 中一样),因为不能保证不变性。不仅不能保证,而且程序员可能会错误地理解不可变性的保证,并基于这种假设而犯错误。

至少对于常量,可以保证不变性。常规不可变变量的用途尚不清楚是否可以在任何时候使其可变。

【问题讨论】:

  • 您不是在“升级”,而是将旧值移动到同名的新可变值中。
  • 重要的是要注意,只有在拥有不可变值时才能将它们“升级”为可变值。例如,您不能将不可变的 reference 升级为可变的。如果你拥有一个值,你可以随意使用它——如果你愿意,你可以在任何时候将它移动到一个(im)可变绑定中。诚然,这使得不可变绑定不像不可变引用那么重要。如果要指定一个值是永久可变的,请使用常量。

标签: rust


【解决方案1】:

在 rust 中,您可以升级不可变变量:

let v = Vec::new(); // Immutable
let mut v = v;      // Mutable
v.push("hi");       // Succeeds

这不是升级变量。您正在创建一个变量v 并将其移动到另一个也称为v 的变量中。原来的v 不再可用。在调试模式下,生成的代码可能有两个完全不同的(堆栈)内存地址,第一个和第二个v

降级也是如此。

这似乎违背了不可变变量的全部目的。

一旦你移动了一个值,你就不能再使用它,如果存在对该值的引用,你就不能移动一个值。因此,您永远不会遇到对现在不可变的东西有可变引用的情况。

【讨论】:

  • 我以为是这样,但我不确定。感谢您的确认。然而,这似乎是一个没有区别的区别。显然,"Downgrading" a mutable binding to immutable is quite common in Rust -- stackoverflow.com/a/54595440/6423456。几乎似乎是编译器应该注意和防止的事情,就像它对技术上可能的大量其他情况所做的那样,但不应该这样做(如所有权)。没有对不可变变量的可变引用不是问题。程序员不知道为什么一个所谓的不可变变量发生了变化。
【解决方案2】:

Rust 允许重新定义变量。因此,在您的示例中,您声明了一个新变量 v 并将向量复制到其中:

let v = Vec::new(); // Immutable
let mut v = v;      // New Mutable <—-
v.push("hi");       // Succeeds

因为向量实现了复制特征。

您可以通过借用作为参考,使您的示例(不)按您的预期工作:

let v = Vec::new(); // Immutable
let &mut v = v;      // Doesnt compile
v.push("hi");

【讨论】:

  • 向量不实现Copy。向量被移动到一个新的变量绑定中。另外,您可能指的是第二个代码 sn-p 中的let v = &amp;mut v;
  • 第二个 sn-p 无法编译,因为它的语法无效。
猜你喜欢
  • 2016-01-25
  • 1970-01-01
  • 2023-01-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多