将“ mut”放在变量名之前和“:”之后有什么区别?


77

这是我在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>) { /* ... */ }

对于C ++程序员:区别类似于指针constvspointee常量
legends2k

Answers:


86

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在有意义的情况下结合使用两个限定符()。


11
我懂了。我想这就像在C ++中,您可以拥有int const*vs.int *const实现不同的目标。
吉米·卢

3
@Shepmaster您可能想mut在绑定上添加它,以允许您在结构内部进行突变(如果它是结构)。
斯科特·奥尔森

7
@BeyondSora不思&mut Type作为&(mut Type),而是作为(&mut) Type。关键字mut通常不在类型中使用,但是有一种称为的引用类型&mut
Scott Olson

2
@BeyondSora您可以看到以上答案的最新编辑。基本的解释是,当您可以更改结构时,可以根据需要将其尽可能多地更改到该结构中(其字段,其字段的字段等)。没有const字段。这是安全的,因为Rust保证您可以进行某些突变,其他任何人都不能同时对其进行读取或突变。
Scott Olson

2
@didierc是的。你能想到的&T&mut T作为糖Ref<T>RefMut<T>(类型我只是做了)。
斯科特·奥尔森

92

如果您来自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采用“白名单”方法,其中,如果希望某些事物是易变的,则必须如此明确地说。


3
这是一张很棒的桌子。可能值得指出的是,&mut T引用也类似于T* restrictC中的指针:它们可能没有别名。&T引用没有这种约束,并且没有类似于非restrict限定T*指针的引用类型。
trentcl

1
我没有C语言背景,但是我仍然认为这(用注释)更好地说明了这一点,而不是公认的答案,有时候简单一点比长一点更好。
kres0345
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.