Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rust:可变与不可变 #54

Open
hello2dj opened this issue Sep 10, 2019 · 0 comments
Open

rust:可变与不可变 #54

hello2dj opened this issue Sep 10, 2019 · 0 comments

Comments

@hello2dj
Copy link
Owner

hello2dj commented Sep 10, 2019

需要读者了解 rust 基本语法

不包括内部可变性,以及原始指针

示例

非引用类型

非引用类型是指本身不是引用,且不包含引用类型字段

不可变

  1. let 变量绑定就是不可变,不可变有两层:在引用类型的说明中我们更能看出这两层含义
    • 变量本身不可重新绑定
    • 绑定对象不可修改
      • 若是 struct 类型,其中的字段也不允许改变

非引用类型,若是 let 绑定则任何改动都是不允许的

let a = 23;
a = 34; // wrong 

struct Person {
    age: i32,
    name: String,
}

let p = Person { age: 32, name: "dj".to_string() };
p.age = 34; // wrong,结构体字段不允许修改
p = Person { age: 56, name: "dj".to_string() }; // 变量不可重新绑定

let vector = vec![1,2,3];
vector[0] = 2;

可变

  1. let mut 变量绑定就是可变,可变有两层
    • 变量本身可重新绑定
    • 若是 struct 类型,其中的字段也允许改变

非引用类型,若是 let mut 绑定则任何改动都是允许的

let mut b = 34;
b = 65;

struct Person {
    age: i32,
    name: String,
};
let mut p1 = Person { age: 23, name: "dj".to_string() };
p1.age = 56;
assert_eq!(p1.age, 56);
p1 = Person { age: 34, name: "dj".to_string() };

let mut vector = vec![1,2,3];
vector[0] = 2;
    
assert_eq!(vector[0], 2);

彩蛋示例中我们也可以看出来,rust 是支持变量重新声明的

引用类型

我们分两步

基本数据类型的引用以及不包含引用的 strcut 类型的引用

  1. 不可变引用:变量持有者无法修改被引用对象

    • 声明不可变引用
      let a = 34;
      let b = &a;
      println!("{}", b); // 我们可以打印 b
      *b = 45; // wrong 不可以改变引用对象
      
      struct Person {
          age: i32,
          name: String,
      };
      
      let p1 = Person { age: 23, name: "dj".to_string() }; // 声明并绑定 p1 变量,资源持有者
      let p2 = &p1;
      p1.age = 34; // wrong 不能修改引用对象
      
      let mut d = 45;
      let b = &d; // 这里可以看出,可变绑定可以作为不可变引用,反之不可

    如上: b 的类型就是不可变引用,还得在不可变的两层含义么?此时就更明显了。b 的类型是 &i32, b 的引用对象我们不能改变。再看 b 本身,他的声明是 不可变绑定,意味着 b 本身也不可重新绑定。

  2. 可变引用:变量持有者可以修引用对象

    • 声明可变引用

      • 被引用对象必须是可变的
     let a = 34;
     let b = &mut a; // wrong a 是不可变的
     
     let mut c = 45;
     let b = &mut c; // 正确
     *b = 23 + 34;
     assert_eq!(c, 57); // c === 57
     
     let mut d = 34;
     b = &mut d; // wrong

    那么 b 的类型就是变引用,还得在不可变的两层含义么?此时就更明显了。b 的类型是 &mut i32, b 的引用对象我可以修改。但是再看 b 本身,他的声明是 不可变绑定,意味着 b 本身也不可重新绑定。

  3. 包含引用类型的 struct

    1. 不可变复合类型包含可变引用

      struct Man<'a> {
      	age: &mut 'a i32,
        name: String,
      }
      
      let mut age = 34;
      let man = Man { age: &mut age, name: "dj".to_string() };
      // man = Man { age: &mut age, name: "dj2".to_string() }; // man 不可重新赋值
      // man.age = &mut age; // man 的字段不可重新赋值
      *man.age = 354;

      这个例子是一个包含引用的结构体,他包含了可变引用。可以看到我们声明的变量 man, man 本身以及字段都是不可重新赋值的,但是由于 age 字段是可变引用,所以 man 的 age 是可以修改的。此时的 age 就好比是 let age: &mut i32 = &mut a

    2. 可变复合类型包含不可变引用

      struct Woman<'a> {
      	age: &'a i32,
        name: String,
      }
      
      let mut age = 34;
      let mut age2 = 56;
      let mut woman = Woman { age: &age, name: "dj".to_string() };
      woman = Woman { age: &age, name: "dj2".to_string() }; // woman 可重新赋值
      woman.age = &mut age2; // man 的字段可重新赋值
      // *woman.age = 354; // wrong 不可以修改字段值

      从这个例子我们又可以得到一个彩蛋,可变类型是可以赋值给不可变类型的 woman.age = &mut age2

    3. 多级引用

      let a = 34;
      let b = &a;
      let c = &b; // 此时 c 的类型就是 & & i32
      
      let d = 45;
      let mut e = &d;
      let f = &mut e; // 此时 f 的类型就是 &mut &i32

总结

对于 rust 的可变与不可变要有针对性的看待,不是声明为可变类型就代表一定可变。对于基本类型是的,但对于复合类型就要看复合类型本身是否包含引用类型。

  1. 对于基本类型

    • 声明为可变即变量本身可以重新绑定,并且可以修改其内容
    • 声明为不可变则相反,都不可改变
  2. 对于复合类型

    • 声明为可变
      • 变量本身可以重新绑定
      • 内部字段也可重新绑定
        • 若内部字段是不可变引用,则内部字段内容不可修改
        • 其他则均可
    • 声明为不可变
      • 变量本身不可以重新绑定
      • 内部字段也不可重新绑定
        • 若内部字段是可变引用,则内部字段内容可以修改
        • 其他则均不可
  3. 可变引用可以赋值给不可变引用,反之不行。这也是情理之中的,既然知道他是不可变,那赋值给他也没事儿。(但真的没事儿么?)```

@hello2dj hello2dj changed the title rust 可变与不可变 rust:可变与不可变 Sep 10, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant