Rust_CommonConcept

  • Rust中的变量默认是不可变的, 但是可以添加mut关键字使之可变

    Rust有单次赋值(Single assignment)原则, 尽管Rust变量默认是不可变的, 但是它允许你在声明变量后延迟赋值一次, 只要编译器能确定该变量只会被赋值一次即可.

    1
    2
    3
    4
    5
    6
    7
    // 下面的语句是可以通过编译的
    let x;
    if cond {
    x = 1;
    } else {
    x = 2;
    }
  • 常量声明方式:

    1
    const THREE_HOURS_IN_SENCONDS: u32 = 60 * 60 * 3;

    常量不允许使用mut关键字来修饰, 也就是说常量是不可改变的.

    常量存活在程序运行的整个生命周期, 也就是说在常量定义的范围内一直生效

  • Shadowing: 新变量覆盖了旧变量,导致在特定作用域内旧变量的值不可见

  • 数据类型

    整形:DataType

    其中,有符号数采用二进制补码存储, isizeusize取决于计算机的架构

    另外编译的时候,如果使用debug模式, 编译器会检查整形溢出. 但是如果采用release模式, 则不会进行溢出检查, 而是会类型回绕

浮点数: 默认为f64, 根据IEEE-754标准表示

布尔类型: true false

字符类型: 一个Rust字符占4字节, 可以表示其他语言, 并且零宽空格也是有效的char值

元组类型: 固定长度, 元组中的元素类型不必相同

1
let tup: (i32, f64, u8) = (500, 6.4, 1);

​ 可以通过模式匹配(pattern matching)解构元组值:

1
2
3
let tup = (500, 6.4, 1);
let (x, y, z) = tup;
println!("The value of y is {y}");

​ 也可以通过点(.)来获取每个位置的元素

1
2
3
4
let x: (i32, f64, u8) = (500, 6.4, 1);
let one = x.0;
let two = x.1;
let three = x.2;

​ 空元组也叫单元(unit), 这个值及对应类型都写作(), 代表空值或者空返回类型.如果表达式没有返回其他任何值, 则隐式返回单元值.

数组类型: 固定长度, 每个元素类型都相同

​ 声明方式:

1
2
3
4
5
6
let months = ["January", "February", "March", "April", "May", "June", "July",
"August", "September", "October", "November", "December"];

let a: [i32; 5] = [1, 2, 3, 4, 5]; // 声明为5个i32类型

let a = [3; 5]; // 生成5个3

​ 可以通过中括号声明, eg: months[1], month[2] st.

  • Statements(语句) 和 Expressions(表达式)

    • 语句是执行某些操作但不返回值的操作

      • let 绑定

        1
        let x = 5;
      • 表达式语句

        1
        2
        let y = 6;
        y + 1; // 这是一个语句, y + 1的结果被丢弃了
      • 函数定义

      • 宏调用(作为语句): println!("Hello, world!"); (虽然 println! 是一个宏,但当它用作打印输出时,通常作为不返回值的语句使用)

      • 任何以分号结尾的表达式:

    • 表达式是 Rust 中会计算并产生一个值的代码块。它们可以由字面量、变量、运算符、函数调用、宏调用,甚至由花括号包围的代码块组成。可以用于赋值, 并且通常不以分号结尾, 如果以分号结尾,它就会变成一个语句, 其返回值会被丢弃.

      1
      2
      3
      4
      5
      let y = {
      let x = 3;
      x + 1 // 这是一个表达式, 返回4
      };
      // now y is 4

    总结区别

    特性 表达式 (Expressions) 语句 (Statements)
    返回值 会返回值 不返回值
    结尾 通常不以分号结尾(在作为代码块的最后一行时) 通常以分号结尾
    目的 计算并产生一个值 执行一个操作
    例子 1 + 2, { let x = 3; x + 1 }, if cond { 1 } else { 0 } let x = 5;, println!("Hello!");, x = 10;
  • 函数

    声明方法:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    fn main() {
    println!("hello, wworld!");

    another_funtion();
    }

    fn another_funtion(x: i32) { // 必须定义函数形参的类型
    prinlin!("Another funtion.");
    println!("The value of x is: {x}");
    }

    fn plus_one(x: i32) {
    x + 1
    }

    fn f(x: i32) -> i32 { // 有返回值的函数
    x + 1
    // return x + 1; // 显式返回也可以
    }

    Rust不在乎在哪里定义函数(调用前, 调用后), 只要函数被定义在调用者可以看到的作用域中即可.

  • 控制流

    • 条件控制

      1
      2
      3
      4
      5
      6
      7
      8
      9
      fn main() {
      let number = 3;

      if number < 5 { // if 后面一定是跟一个bool类型, 如果是其他类型并不会隐式转换为bool类型
      println!("condition was true");
      } else {
      println!("condition was false");
      }
      }
      1
      2
      3
      4
      5
      6
      7
      fn main() {
      let condition = true;

      let number = if condition { 5 } else { 6 }; // 这里的两个分支都必须是相同的类型, 不然会报错

      println!("The value of number is {number}. ");
      }

      因为Rust需要在编译时需要知道变量的类型, 而不是运行时再做推断, 所以如果使用上面的语句来进行赋值的时候, 不同分支返回的都必须是相同的类型.

    • 循环

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      fn main() {
      let mut cnt = 0;
      let result = loop {
      cnt += 1;

      if cnt == 10 {
      break cnt * 2; // 使用break 中断循环并且返回值
      };
      }

      println!("The result is {result}");
      }

      如果有嵌套循环, 可以通过标签来标注某个特定的循环并且可以break掉特的循环:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      fn loopwithlabels() {
      let mut cnt = 0;
      'counting_up: loop { // 使用单引号来声明一个标签
      println!("cnt = {cnt}");
      let mut remaining = 10;

      loop {
      println!("remaining = {remaining}");
      if remaining == 9 {
      break;
      }
      if cnt == 2 {
      break 'counting_up;
      }
      remaining -= 1;
      }

      cnt += 1;
      }

      println!("End cnt = {cnt}");
      }

      while 循环: 与其他语言十分相似

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      fn main() {
      let mut number = 3;

      while number != 0 {
      println!("{number}");

      number -= 1;
      }

      println!("LIFTOFF!!");
      }

      遍历集合:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      /* 通过while循环来遍历 */
      fn main() {
      let a = [10, 20, 30, 40, 50];
      let mut idx = 0;

      while idx < 5 {
      println!("the value is {}", a[idx]);

      idx += 1;
      }
      }

      /* 通过for循环遍历, 推荐 */
      fn main() {
      let a = [10, 20, 30, 40, 50];

      for element in a {
      println!("the value is {element}");
      }
      }