示例代码:
use std::sync::atomic::{AtomicU32, Ordering};
#[derive(Debug)]
struct Token(u32);
impl Token {
fn new() -> Self {
static COUNTER: AtomicU32 = AtomicU32::new(1);
let inner = COUNTER.fetch_add(1, Ordering::Relaxed);
Token(inner)
}
}
fn main() {
let t1 = Token::new();
let t2 = Token::new();
let t3 = Token::new();
println!("{:?}\n{:?}\n{:?}", t1, t2, t3);
}
Run Code Online (Sandbox Code Playgroud)
当我运行上面显示的代码片段时,它会打印:
Token(1)
Token(2)
Token(3)
Run Code Online (Sandbox Code Playgroud)
我在 Rust 参考中发现静态项的初始化是在编译时评估的。
我想知道当程序执行到初始化变量的行时,运行时到底发生了什么COUNTER。编译后的代码是什么样子的,以便它可以忽略初始化?
Fra*_*gné 11
static无论变量是在模块级别还是在函数级别定义,它们的处理方式都是相同的。唯一的区别是名称解析的范围。
许多可执行文件格式(包括ELF和PE)在各个部分中构造程序。通常,函数代码位于一个部分中,可变全局变量位于另一部分中,常量(包括字符串文字)位于另一部分中。当操作系统将程序加载到内存中时,这些部分将被映射到具有不同内存保护选项(例如,常量不可写)的内存中,如可执行文件中所指定的那样。
当文档说static项目在编译时初始化时,这意味着编译器在编译时确定该项目的初始值,然后将该值写入已编译的二进制文件中的适当部分。当你的程序运行时,在你的程序有机会运行一条指令之前,该值就已经在内存中了。
编译器能够计算表达式,AtomicU32::new(1)因为AtomicU32::new它被定义为const fn. 添加const到函数定义意味着它可以在编译时计算的表达式中使用,但const fns 的功能比常规函数要有限得多。但在这种情况下AtomicU32::new,函数需要做的就是初始化AtomicU32结构,它只是u32.
| 归档时间: |
|
| 查看次数: |
4430 次 |
| 最近记录: |