Constant items
常量项
constant-items.md
commit: 021889f26215721860a153e692909eda7cfd7a6e
本章译文最后维护日期:2023-05-03
句法
ConstantItem :
const
( IDENTIFIER |_
):
Type (=
Expression )?;
常量项是一个可选的具名 常量值,它与程序中的具体内存位置没有关联。无论常量在哪里使用,它们本质上都是内联的,这意味着当它们被使用时,都是直接被拷贝到相关的上下文中来使用的。这包括使用非拷贝(non-Copy
)类型的值和来自外部的 crate 的常量。对相同常量的引用不保证它们引用的是相同的内存地址。
常量必须显式指定数据类型。类型必须具有 'static
生存期:程序初始化器(initializer)中的任何引用都必须具有 '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, }; }
常量表达式只能在trait定义中省略。
Constants with Destructors
常量与析构函数
常量可以包含析构函数。析构函数在值超出作用域时运行。1
#![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 在函数的结尾处通过调用 drop 方法被销毁。 // 打印出 "Dropped. Held 0.". } }
Unnamed constant
未命名常量
不同于关联常量,自由常量(free constant)可以使用下划线来命名。例如:
#![allow(unused)] fn main() { const _: () = { struct _SameNameTwice; }; // OK 尽管名称和上面的一样: const _: () = { struct _SameNameTwice; }; }
与下划线导入一样,宏可以多次安全地在同一作用域中扩展出相同的未具名常量。例如,以下内容不应该产生错误:
#![allow(unused)] fn main() { macro_rules! m { ($item: item) => { $item $item } } m!(const _: () = ();); // 这会展开出: // const _: () = (); // const _: () = (); }
Evaluation
求值
自由常量总是在编译时进行计算,以消除 panics。即使在未使用的函数中也会发生这种情况:
#![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); } }
1
在程序退出前,析构销毁的只是其中的一份拷贝;这句还有另一层含义是常量在整个程序结束时会调用析构函数。