web-dev-qa-db-ja.com

変数名の前と「:」の後に「mut」を置くことの違いは何ですか?

Rustのドキュメントで見た2つの関数シグネチャは次のとおりです。

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>) { /* ... */ }
60
Jimmy Lu

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は有効な構文ではありません。 2つの修飾子(let mut a: &mut T)、それが理にかなっているとき。

55
Shepmaster

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は「ホワイトリスト」アプローチを採用します。変更可能であることを明示的に言う必要があります。

57
anderspitman