为何Rust中const函数可引用static,而const值却无法引用?
Rust中const变量与const函数引用static原子变量的差异
问题场景
先定义一个static原子变量:
static FOO: AtomicI32 = AtomicI32::new(2);
情况1:const变量引用static变量(编译报错)
编写如下代码会触发编译错误:
const FOO_CONST: &'static AtomicI32 = &FOO;
错误信息:
error[E0080]: it is undefined behavior to use this value | 57 | const FOO_CONST: &'static AtomicI32 = &FOO; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered reference to mutable memory in `const` | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { ╾──────alloc368───────╼ │ ╾──────╼ }
情况2:const函数返回static变量的引用(编译正常)
编写如下const函数则可以正常编译:
const fn get_foo() -> &'static AtomicI32 { &FOO }
测试代码验证指向同一个AtomicI32:
println!("{}", get_foo().load(Ordering::SeqCst)); FOO.fetch_add(1, Ordering::SeqCst); println!("{}", get_foo().load(Ordering::SeqCst)); // Output // 2 // 3
提问:原本以为两者底层逻辑一致,为何仅const函数可以正常工作?
原因解释
核心差异在于Rust对const变量和const函数的求值规则与安全约束不同:
const变量的约束
const变量的值会在编译期完全计算完成,并作为常量嵌入到程序二进制中。Rust要求const变量必须是编译期安全的不可变值,不允许引用运行期可变的内存区域——AtomicI32属于可修改的内存(即使是static变量,它支持原子操作修改),直接将&FOO赋值给const变量,相当于在编译期创建了一个指向可变内存的常量引用,这违反了const变量的安全规则,会被判定为可能导致未定义行为(UB),因此触发编译错误。const函数的约束
const函数的设计允许在编译期或运行期执行:
- 当在运行期调用
get_foo()时,它只是返回static变量FOO的内存地址,和普通获取static引用的逻辑完全一致,不存在安全问题; - 即使在编译期调用,因为static变量的内存地址是编译期确定的固定值,返回这个地址的引用是合法的——Rust允许const函数返回指向'static生命周期变量的引用,无论该变量是否可变,只要函数本身的逻辑符合const函数的执行规则(这里仅取static变量的引用,属于合法操作)。
简单来说,const变量被当作不可变的编译期常量,而const函数更像一个可以在编译期执行的工具,返回的引用只要目标是'static的,就不受“不可变”的约束。
内容的提问来源于stack exchange,提问作者Noxmore
相关产品推荐
相关产品推荐

