std::atomic_ref为已存在变量提供临时原子访问能力,不创建新对象,需满足对齐和生命周期约束,仅支持trivially copyable且对齐足够的类型,非内存管理型视图。
std::atomic_ref 用来给普通变量临时加原子性
它不创建新对象,而是为已存在的
类型变量(如全局数组元素、结构体字段、栈上变量)提供原子访问能力。核心价值在于:避免为每个需要原子操作的变量都声明成
,尤其当这些变量大部分时间并不需要原子性,只在少数同步点才需保护时。
必须满足对齐和生命周期约束,否则行为未定义
构造时会检查底层对象是否满足原子操作所需的对齐要求(通常为
),且该对象在整个
生命周期内不能被销毁或移动。常见翻车点:
对栈上局部变量使用
后,又在函数返回后继续访问 —— 悬垂引用
对
元素取
,但 vector 发生了 reallocation —— 原地址失效
对 packed 结构体成员(如
)构造
—— 对齐不足,
构造可能抛
或直接 UB
支持的类型有限,不是所有 T 都能用
只有满足
且对齐足够(至少
)的类型才能用于
。常见可用类型包括:
、
、
、
;不可用类型包括:
、含虚函数的类、非 trivially copyable 的自定义结构体。
例如,下面这段代码是合法的:
立即学习
“
C++免费学习笔记(深入)
”;
C函数速查手册(CHM版)
C函数速查手册(CHM版)
下载
但若写成:
不能替代 std::atomic,也不提供默认初始化语义
是“视图”,不是“容器”。它不管理内存,不参与对象生命周期,也不隐式保证初始值的原子可见性。比如:
不能像
那样带初值构造 —— 必须已有确定值的变量
多个线程同时通过不同
绑定到同一变量是允许的,但必须确保无数据竞争(即不能一个线程用
写,另一个用普通读)
如果原变量被其他非原子代码修改,
的操作仍能保证自身原子性,但无法防止与非原子访问之间的竞态 —— 这是使用者的责任
最容易被忽略的是:**对齐检查只在运行时构造发生,且某些平台(如 ARM)对未对齐原子操作直接触发硬件异常,而不是静默降级**。务必在绑定前确认目标变量地址满足
,必要时用
显式对齐。
Tstd::atomicstd::atomic_refalignof(T)std::atomic_refstd::atomic_refstd::vectorstd::atomic_refstruct __attribute__((packed)) S { char a; int b; };std::atomic_refstd::atomic_refstd::bad_optional_accessstd::is_trivially_copyable_valignof(T)std::atomic_refintlong longvoid*std::shared_ptrstd::stringint x = 42;
std::atomic_ref ref{x};
ref.fetch_add(1, std::memory_order_relaxed); // x 变成 43 std::string s = "hello";
std::atomic_ref bad_ref{s}; // 编译失败:std::string 不满足 is_trivially_copyable std::atomic_refstd::atomic a{0}; std::atomic_refatomic_refstd::atomic_refalignof(T)alignas