常量项

语法

ConstantItem :

   const ( 标识符 | _ ) : 类型 ( = 表达式 )? ;

常量项是一个可选命名的常量值,它不与程序中的特定内存位置相关联。常量本质上是在使用它们的地方内联的,这意味着它们在使用时会被直接复制到相关的上下文中。这包括使用来自外部包的常量,以及非Copy类型。对同一个常量的引用不一定保证指向同一个内存地址。

常量必须显式指定类型。该类型必须具有'static生命周期:初始化器中的任何引用都必须具有'static生命周期。

常量可以引用其他常量的地址,在这种情况下,地址将在适用时省略生命周期,否则——在大多数情况下——默认为static生命周期。(请参阅静态生命周期省略。)但是,编译器仍然可以自由地多次转换常量,因此引用的地址可能不稳定。

#![allow(unused)]
fn main() {
const BIT1: u32 = 1 << 0;
const BIT2: u32 = 1 << 1;

const BITS: [u32; 2] = [BIT1, BIT2];
const STRING: &'static str = "bitstring";

struct BitsNStrings<'a> {
    mybits: [u32; 2],
    mystring: &'a str,
}

const BITS_N_STRINGS: BitsNStrings<'static> = BitsNStrings {
    mybits: BITS,
    mystring: STRING,
};
}

只有在特征定义中才可以省略常量表达式。

具有析构函数的常量

常量可以包含析构函数。当值超出作用域时,将运行析构函数。

#![allow(unused)]
fn main() {
struct TypeWithDestructor(i32);

impl Drop for TypeWithDestructor {
    fn drop(&mut self) {
        println!("Dropped. Held {}.", self.0);
    }
}

const ZERO_WITH_DESTRUCTOR: TypeWithDestructor = TypeWithDestructor(0);

fn create_and_drop_zero_with_destructor() {
    let x = ZERO_WITH_DESTRUCTOR;
    // x gets dropped at end of function, calling drop.
    // prints "Dropped. Held 0.".
}
}

未命名常量

关联常量不同,自由常量可以通过使用下划线而不是名称来保持未命名。例如

#![allow(unused)]
fn main() {
const _: () =  { struct _SameNameTwice; };

// OK although it is the same name as above:
const _: () =  { struct _SameNameTwice; };
}

下划线导入一样,宏可以在同一个作用域中安全地多次发出相同的未命名常量。例如,以下代码不应产生错误

#![allow(unused)]
fn main() {
macro_rules! m {
    ($item: item) => { $item $item }
}

m!(const _: () = (););
// This expands to:
// const _: () = ();
// const _: () = ();
}

求值

自由常量总是在编译时求值以暴露恐慌。即使在未使用的函数中也会发生这种情况

#![allow(unused)]
fn main() {
// Compile-time panic
const PANIC: () = std::unimplemented!();

fn unused_generic_function<T>() {
    // A failing compile-time assertion
    const _: () = assert!(usize::BITS == 0);
}
}