在 Rust 中,常量表达式(const)在编译阶段计算,使得在程序运行之前创建的值成为程序的一部分。这种表达式用于指定数组的大小、静态结构中的值、泛型参数以及其他需要具有固定已知值的不变常量的情况。
在 Rust 中,可以创建“常量”函数(const fn),可以在其他常量表达式中使用或用于初始化常量变量。编译器保证此表达式不包含不允许的操作(例如,内存访问)。
示例:
const fn fib(n: u32) -> u32 { match n { 0 | 1 => 1, _ => fib(n - 1) + fib(n - 2), } } const F8: u32 = fib(8); const ARR: [u32; F8 as usize] = [0; F8 as usize]; // 数组大小为 34
在此示例中,值 F8 和数组 ARR 的大小在编译阶段计算。
const函数与普通函数有什么区别?是否可以将任何函数声明为 const fn?
回答:
不,并不是所有函数都可以声明为 const fn。const fn 只能包含允许的操作,不允许有副作用或不安全的内存操作。例如,不能在 const fn 中打开文件或动态分配内存。
const fn add(x: i32, y: i32) -> i32 { x + y // 合法 } // 这个不会编译: const fn fail() -> String { // 错误! String::from("err") }
故事
在一个项目中,试图通过常量函数在编译阶段计算字符串的哈希值,但在此函数内使用了
HashMap中的标准方法和内存分配。程序无法编译,抛出了关于在 const fn 中不允许操作的无法理解的错误。
故事
在大型嵌入式开发中,开发者定义了一个需要在编译阶段计算的字段的常量结构,但在初始化中使用了未标记为
const fn的外部 crate 的函数。这导致无法使用该逻辑来确定静态缓冲区的大小。
故事
在代码中混淆了
static和const的区别,试图在执行时修改“常量”,并得到了隐式的 UB(未定义行为),因为在 Rust 中,常量并不像值那样存储在内存中,而是由编译器在使用位置进行替换,这根本不意味着他们可以被修改。