跳转到主内容
新派编程网 - 新潮编程理念,全新技术课堂!

c++20的std::atomic_ref有什么用? (对非原子对象进行原子操作)

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

相关文章