• const 和 static
    • static
    • 可变性
    • 初始化
    • 我应该用哪个?(Which construct should I use?)

    const 和 static

    const-and-static.md


    commit ccb1d87d6faa9ff528d22b96595a0e2cbb16c0f2

    Rust 有一个用const关键字定义常量的方法:

    1. const N: i32 = 5;

    与let绑定不同,你必须标注一个const的类型。

    常量贯穿于整个程序的生命周期。更具体的,Rust 中的常量并没有固定的内存地址。这是因为实际上它们会被内联到用到它们的地方。为此对同一常量的引用并不能保证引用到相同的内存地址。

    static

    Rust 以静态量的方式提供了类似“全局变量”的功能。它们与常量类似,不过静态量在使用时并不内联。这意味着对每一个值只有一个实例,并且位于内存中的固定位置。

    这是一个例子:

    1. static N: i32 = 5;

    与let绑定不同,你必须标注一个static的类型。

    静态量贯穿于整个程序的生命周期,因此任何存储在常量中的引用有一个'static生命周期:

    1. static NAME: &'static str = "Steve";

    可变性

    你可以用mut关键字引入可变性:

    1. static mut N: i32 = 5;

    因为这是可变的,一个线程可能在更新N同时另一个在读取它,导致内存不安全。因此访问和改变一个static mut是不安全(unsafe)的,因此必须在unsafe块中操作:

    1. # static mut N: i32 = 5;
    2. unsafe {
    3. N += 1;
    4. println!("N: {}", N);
    5. }

    更进一步,任何存储在static的类型必须实现Sync

    初始化

    conststatic都要求赋予它们一个值。它们必须只能被赋予一个常量表达式的值。换句话说,你不能用一个函数调用的返回值或任何相似的复合值或在运行时赋值。

    我应该用哪个?(Which construct should I use?)

    几乎所有时候,如果你可以在两者之间选择,选择const。实际上你很少需要你的常量关联一个内存位置,而且使用const允许你不止在在自己的包装箱还可以在下游包装箱中使用像常数扩散这样的优化。

    一个常量可以看作一个 C 中的#define:它有元数据开销但无运行时开销。“我应该在 C 中用一个 #define 还是一个 static 呢?”大体上与在 Rust 你应该用常量还是静态量是一个问题。