在变量名之前和":"之后放置"mut"有什么区别?

Jim*_* Lu 51 variables syntax reference mutable rust

这是我在Rust文档中看到的两个函数签名:

fn modify_foo(mut foo: Box<i32>) { *foo += 1; *foo }
fn modify_foo(foo: &mut i32) { *foo += 1; *foo }
Run Code Online (Sandbox Code Playgroud)

为什么不同的位置mut

似乎第一个函数也可以声明为

fn modify_foo(foo: mut Box<i32>) { /* ... */ }
Run Code Online (Sandbox Code Playgroud)

and*_*man 63

如果你是来自C/C++,那么基本上这样想也可能会有所帮助:

// Rust          C/C++
    a: &T     == const T* const a; // can't mutate either
mut a: &T     == const T* a;       // can't mutate what is pointed to
    a: &mut T == T* const a;       // can't mutate pointer
mut a: &mut T == T* a;             // can mutate both
Run Code Online (Sandbox Code Playgroud)

你会注意到这些是彼此的反转.C/C++采用"黑名单"方法,如果你想要一些东西是不可变的,你必须明确地说,而Rust采用"白名单"方法,如果你想要一些可变的东西,你必须明确说出来.

  • 这是一张很棒的桌子。值得注意的是,“&amp;mut T”引用也类似于 C 中的“T*restrict”指针:它们可能没有别名。“&amp;T”引用没有这样的约束,并且没有类似于非“restrict”限定的“T*”指针的引用类型。 (4认同)
  • 我没有 C 背景,但我仍然认为这比接受的答案更好地解释了它(带有注释),有时更简单比更长更好。 (2认同)

She*_*ter 59

mut foo: T意味着你拥有了一个名为变量foo是一个T.您可以更改变量引用的内容:

let mut val1 = 2;
val1 = 3; // OK

let val2 = 2;
val2 = 3; // error: re-assignment of immutable variable
Run Code Online (Sandbox Code Playgroud)

这也允许您修改您拥有的结构的字段:

struct Monster { health: u8 }

let mut orc = Monster { health: 93 };
orc.health -= 54;

let goblin = Monster { health: 28 };
goblin.health += 10; // error: cannot assign to immutable field
Run Code Online (Sandbox Code Playgroud)

foo: &mut T意味着你有一个引用(&)值的变量,你可以改变(mut)引用的值(包括字段,如果它是一个结构):

let val1 = &mut 2;
*val1 = 3; // OK

let val2 = &2;
*val2 = 3; // error: cannot assign to immutable borrowed content
Run Code Online (Sandbox Code Playgroud)

请注意,&mut只有引用才有意义 - foo: mut T不是有效的语法.let mut a: &mut T当有意义时,您还可以组合两个限定符().

  • 我知道了.我想这就像在C++中你可以使用`int const*`与`int*const`来实现不同的东西. (9认同)
  • @BeyondSora不要把`&mut Type`想象成`&(mut Type)`,而是``&(mut)Type`.关键字"mut"一般不用于类型,但有一种名为`&mut`的引用. (6认同)
  • @Shepmaster你可能想要在绑定上添加`mut`允许你在结构内变异(如果它是一个结构). (3认同)
  • @ScottOlson 所以,你说的是 `&amp;mut` 只是一个“方便”的符号,以避免引入新的关键字,但实际上它与 lhs 通常的 `mut` 关键字是一个不同的概念? (3认同)
  • @BeyondSora您可以看到上述答案的最新编辑.基本的解释是当你可以改变一个结构时,你可以根据需要改变结构(它的字段,字段的字段等).没有`const`字段.这是安全的,因为Rust保证当你可以改变某些东西时,没有其他人可以同时读取或改变它. (2认同)
  • @didierc是的.您可以将`&T`和`&mut T`视为`Ref <T>`和`RefMut <T>`(我刚刚编写的类型)的糖. (2认同)
  • 虽然“&amp;mut”的技术名称是一种模式,但我建议在开头将“&amp;”、“&amp;mut”视为关键字或标记,与关键字“mut”无关,以减少混淆。 (2认同)

Geo*_*rge 39

下面的自然语言翻译似乎让我明白了......

let x = value;
  x {binds immutably} to {immutable value}

let mut x = value;
  x {binds mutably} to {possibly mutable value}

let x = &value;
  x {binds immutably} to {a reference to} {immutable value}

let x = &mut value;
  x {binds immutably} to {a reference to} {mutable value}

let mut x = &value;
  x {binds mutably} to {a reference to} {immutable value}

let mut x = &mut value;
  x {binds mutably} to {a reference to} {mutable value}
Run Code Online (Sandbox Code Playgroud)

在哪里

  • {binds mutably}意味着绑定可以重新分配
  • {mutable value}意味着值的内容可以改变
  • 为了能够改变一个值,你需要一个可变绑定和一个可变值

笔记:

参考可变性与目标可变性

x诸如 之类的引用变量是与其指向的let x = &mut y目标变量不同的变量。y特别是,x在堆栈上有自己的位置和可变权限。因此,如果x是不可变的,就像这里一样,那么它不能被重新分配以指向某个其他变量。该限制与通过它突变目标的能力是分开的,如*x = some_value;目标是一个独特的变量,具有自己的可变性权限。但是,如果w是可变的,如 中所示let mut w = &mut p,那么它确实可以重新分配以指向其他类似类型的变量:w = &mut z