What's the difference between placing "mut" before a variable name and after the ":"?

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

fn modify_foo(mut foo: Box<i32>) { *foo += 1; *foo }
fn modify_foo(foo: &mut i32) { *foo += 1; *foo }

为什么 mut的位置不同?

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

fn modify_foo(foo: mut Box<i32>) { /* ... */ }
17719 次浏览

mut foo: T means you have a variable called foo that is a T. You are allowed to change what the variable refers to:

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


let val2 = 2;
val2 = 3; // error: re-assignment of immutable variable

This also lets you modify fields of a struct that you own:

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

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

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


let val2 = &2;
*val2 = 3; // error: cannot assign to immutable borrowed content

请注意,&mut只对引用有意义-foo: mut T不是有效的语法。如果有意义,还可以组合这两个限定符(let mut a: &mut T)。

如果你来自 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

你会注意到这些是彼此的倒数。C/C + + 采用“黑名单”的方法,如果你想要某些东西是不可变的,你必须明确地说出来,而 Rust 采用“白名单”的方法,如果你想要某些东西是可变的,你必须明确地说出来。

下面的自然语言翻译似乎为我澄清了一些事情..。

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}

哪里

  • {binds mutably}表示可以重新分配绑定
  • {mutable value}表示值的内容可以更改
  • 为了能够得到一个 mutate值,你需要一个 可变结合可变结合和一个 可变价值可变价值

参考类别变量

当你

let mut x: &T = value;

这意味着 x是变量,是指T的一个实例,就好像通过将 T实例的内存地址存储在 x的值中一样。这个 参考文献(即“内存地址”)是这个上下文中可变性的主题: 可以修改 x以引用 T的不同实例,如下所示:

x = some_other_T_instance;

参照物(即 x所指的 T实例的值)不能透过 x更改:

// Illegal
*x = a_different_value;

可变引用类型的不可变变量

When you have

let x: &mut T = value;

这意味着 x是一个引用 T的可变实例的变量。在这种情况下,参照物(即实际值)是可变性的主题。可以像这样通过引用修改它

*x = some_other_value;

但是引用本身(即变量 x中的“内存地址”)不能:

// illegal
x = a_different_value;