COPY FROM: https://mp.weixin.qq.com/s?__biz=MzU5MDQ5NTIyNg==&mid=2247483841&idx=1&sn=be8d2bdbdf8dbe3596fe69d743b9af7c

概述

话说 StackOverflow 上有个哥们问了一个问题,正如标题所述,它问的是下面这段代码里:

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

代码里的 mut 放在 mut foo: Box<i32>foo: &mut i32 的区别是什么?

下面是结论,没有 C/C++编程经验的童鞋可以忽略中间这一栏

Rust C/C++ 含义 正式(拗口)版解释
a: &T const T* const a 都不能修改 不可变引用的不可变绑定
mut a: &T const T* a 不能修改 a 指向的内容 不可变引用的可变绑定
a: &mut T T* const a 不能修改 a 可变引用的不可变绑定
mut a: &mut T T* a 都能修改 可变引用的可变绑定

mut a:&T

先来看 mut a : Tmut a : &T 的区别,这个应该比较简明,即前者中a是T类型变量的可变绑定,后者中a是T类型不可变引用的可变绑定。(如果对引用的概念还比较模糊,可以参考公众号中翻译的一篇文章:《Rust 中的引用》)下面来看个例子:

  1. struct FullName{
  2. first_name:String,
  3. last_name:String,
  4. }
  5. // mut a:& T
  6. let mut a = & FullName {
  7. first_name: String::from("Jobs"),
  8. last_name: String::from("Steve"),
  9. };
  10. //a重新绑定到一个新的FullName的引用
  11. a = &FullName {
  12. first_name: String::from("Gates"),
  13. last_name: String::from("Bill"),
  14. };
  15. //不允许对a指向的内容作出修改
  16. //a.first_name = String::from("Error");
  17. println!("{}:{}",a.last_name, a.first_name);

这里的 a 是可变的,意思是 a 可以重新绑定另一个结构体的引用,但是不能对结构体里的内容作修改(比如这里对 a.first_name 的赋值就是不允许的),因为引用( &T )是不可变的。

a:&mut T

接着看下面这个例子:

  1. // a:&mut T
  2. let a = &mut FullName {
  3. first_name: String::from("Jobs"),
  4. last_name: String::from("Steve"),
  5. };
  6. //a不允许重新绑定到一个新的FullName的引用
  7. // a = &FullName {
  8. // first_name: String::from("Gates"),
  9. // last_name: String::from("Bill"),
  10. // };
  11. //允许对a指向的内容作出修改
  12. a.first_name = String::from("Gates");
  13. println!("{}:{}",a.last_name, a.first_name);

这里的 a 绑定到了 FullName 的可变引用,也就是说可以对 FullName 进行修改,但是 a 是不可以修改的,即通过 a 修改 FullName 里的字段,如 first_name 是没问题的,但是如果要 a 重新绑定到新的结构体(相当于修改 a )是不行的。

参考资料

  1. https://stackoverflow.com/questions/28587698/whats-the-difference-between-placing-mut-before-a-variable-name-and-after-the
  2. https://stackoverflow.com/questions/29672373/what-is-difference-between-mut-a-t-and-a-mut-t