Подтвердить что ты не робот

Какая разница в `mut` перед именем переменной и после`: `?

Вот две сигнатуры функций, которые я видел в документации 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>) { /* ... */ }
4b9b3361

Ответ 1

mut foo: T означает, что у вас есть переменная с именем foo, которая является T. Вам разрешено изменять переменную на:

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

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

Это также позволяет вам изменять поля структуры, которые у вас есть:

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), когда это имеет смысл.

Ответ 2

Если вы придете с 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/С++ использует подход "черного списка", где, если вы хотите, чтобы что-то было неизменным, вы должны сказать это явно, в то время как Rust использует "белый список", где, если вы хотите, чтобы что-то изменилось, вы должны сказать это явно.