为何std::atomic_ref要求引用对象对齐而std::atomic无此要求?
atomic_ref<T>对引用对象有对齐要求,而std::atomic<T>没有? 核心原因在于两者的内存管理模型和设计定位完全不同:
内存控制权的差异
std::atomic<T>是拥有自身内存的原子对象——编译器在创建它的实例时,会自动确保其内部存储的T满足硬件原子操作要求的对齐规则。哪怕原生T的对齐要求更低,编译器也会通过额外填充字节、调整内存地址等方式,强制让std::atomic<T>实例符合原子操作的对齐标准,开发者完全不用手动干预。
而atomic_ref<T>只是对已有T对象的原子引用,它无法修改被引用对象的内存布局或地址。如果原T对象的对齐不满足硬件原子操作的要求,硬件就无法保证原子性(甚至可能触发未定义行为,比如某些架构下的不对齐内存访问直接崩溃),因此必须要求被引用对象提前具备合适的对齐。设计目标的区别
std::atomic<T>的语义是“这个对象本身就是原子的”,所以保证对齐是它的核心职责之一,编译器必须兜底。atomic_ref<T>的设计目的是为普通T对象提供临时原子操作能力——比如你需要对一个已存在于结构体、数组里的非原子T成员做原子读写,这时候用atomic_ref<T>来包裹它。但这种场景下原对象的对齐是由它自身的定义决定的,atomic_ref<T>无法改变这一点,只能要求用户确保原对象符合对齐要求。无锁操作的依赖逻辑
硬件的无锁原子操作几乎都依赖于数据地址的对齐(比如32位原子操作要求4字节对齐,64位要求8字节对齐)。std::atomic<T>因为由编译器控制内存,其地址必然满足对齐要求,所以它的is_lock_free()结果只和类型、硬件架构有关,是固定的。
但atomic_ref<T>引用的对象如果对齐不足,硬件只能通过加锁的方式模拟原子操作,此时is_lock_free()会返回false。因此对齐直接决定了atomic_ref<T>的操作是否能无锁执行。
内容的提问来源于stack exchange,提问作者mentalmushroom

