返回介绍

2.1 变量

发布于 2024-10-13 11:25:28 字数 2823 浏览 0 评论 0 收藏 0

变量包括命名变量、匿名变量,以及函数形参。除非特别声明,否则变量不可变(immutable)。目的是为了提升安全性和并发性。不可变意味着,值绑定(binding)后不能修改。

不可变是名称绑定行为,并非目标值(内存)不能修改。

fn main() {
  let x: i32 = 1;
  x = 2;
  ^^^^^ cannot assign twice to immutable variable
}
fn main() {
  let mut x: i32 = 1;
  x = 2;
}

可省略类型,通过初始值进行推断(type inference)。字面量有默认类型(例如 i32 ),可添加后缀指定。

use std::mem::size_of_val;

fn main() {
  let x = 1;    // i32
  let y = 2i64;   // i64
  let z = 3_u64;  // u64

  assert_eq!(4, size_of_val(&x));
  assert_eq!(8, size_of_val(&y));
  assert_eq!(8, size_of_val(&z));
}
fn main() {
  let (x, y) = (1, "abc");
  
  assert_eq!(x, 1);
  assert_eq!(y, "abc");
}

变量必须初始化。可将定义和初始化分开,但在使用前必须有初始化操作。

fn main() {
  let x: i32;
  println!("{:?}", x);
           ^ use of possibly-uninitialized `x
}
fn main() {
  let x: i32;
  x = 1;
  println!("{}", x);

  let y: i32;
  {
    y = 100;
  }
  println!("{}", y);
}

未使用变量,编译器给出警告信息。如要保留,添加下划线前缀( _name )。

仅单个下划线表示缺省变量,丢弃。

fn main() {
  let x = 1;
    ^ help: if this is intentional, prefix it with an underscore: `_x`
    
  let _y = 2;
}

同一作用域(scope)内,使用相同名字再次绑定,实际是定义新变量。新定义会遮蔽(shadowing)前同名变量。

fn main() {
  let x: i32 = 1;
  println!("{:p}", &x);   // 两次输出的地址不同。

  let x: &str = "abc";
  println!("{:p}", &x);
}

// 0x7ffe31b509f4
// 0x7ffe31b50a40

之所以是绑定,是因为有抽象的所有权概念。如所有权被转移(move),则该变量名视为未初始化,无法继续使用。

fn main() {
  let a = String::from("abc");
  let b = a;

  println!("{}", b);
  println!("{}", a);
}
error[E0382]: borrow of moved value: `a`

  |
  |   let a = String::from("abc");
  |     - move occurs because `a` has type `String`, 
        which does not implement the `Copy` trait
        
  |   let b = a;
  |       - value moved here
...
  |   println!("{}", a);
  |          ^ value borrowed here after move

局部变量默认是保存在栈(stack)内的值。

尽可能保存在栈内,除非大小未知需动态增长(如 String ),或手动在堆创建(如 Box<T> )。

fn main() {
  let s = String::from("abc");   // alloc::string
  println!("{}", s);       
}                  // drop

全局变量

使用 static 定义,名称大写。且必须显式声明类型,必须有初始化值。

位于 .rodata 或 .data 内。也可用于函数内,实现局部静态变量。

static X: i32 = 100;

fn main() {
  println!("{:?}", X);
}

静态可变可能导致内存安全问题(多线程),须用 unsafe 担保。

static mut X: i32 = 100;

fn main() {
  unsafe {
    println!("{:?}", X);

    X += 1;
    println!("{:?}", X);
  }
}
fn test() {
  static mut X: i32 = 0;
  unsafe {
    X += 1;
    println!("{X}");
  }
}

fn main() {
  for _ in 0..3 {
    test();
  }
}

/*
1
2
3
*/

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文