You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

原子对象的值计算结果是否为未指定行为?C++标准与实例解析

C++原子操作加载结果的确定性分析

标准依据

根据C++标准[intro.races]第14款规定:
原子对象M的值(由求值B确定)应当是某个修改M的副作用A所存储的值,其中B不先于A发生。

这里的“某个修改M的副作用A”指修改顺序中任意一个可能的值,这一点可通过PR #6501确认。

代码实例

std::atomic<int> v{0};
auto c = [](){v.store(1,std::memory_order::release); return 1;}();
auto c2 = [](){v.store(2,std::memory_order::release); return 2;}();

int main(){
   auto r = v.load(std::memory_order::acquire); // #1
}

问题核心

已知#1处的加载操作不会先于上述两个存储操作发生,那么#1处的值计算结果是修改顺序中的最新值,还是可以是0、1、2中的任意一个(即属于未指定行为)?当前编译器实现中结果始终为2,但该结果是否是确定的,还是仅为未指定行为的一种表现?

分析结论

#1处的结果属于未指定行为,理论上可读取到1或2,但绝不可能是0,具体原因如下:

  • 全局变量的初始化(包括两个lambda的立即调用)都发生在main函数执行之前,根据C++标准,这些初始化的副作用(v.store(1)和v.store(2))都happens beforemain中的加载操作#1,因此加载操作不可能读取到初始值0。
  • C++标准并未强制规定这两个release存储操作的执行顺序。实际编译器中结果始终为2,是因为初始化代码按源码顺序执行,v.store(2)在v.store(1)之后完成,修改顺序里2是最新值,但这只是编译器的实现选择,而非标准要求的必然结果。
  • 依据[intro.races] p14的规则,加载操作只需读取任意一个不早于自身发生的存储副作用的值即可,这里两个存储操作都满足条件,因此标准允许读取1或2。编译器返回2只是未指定行为的一种常见表现,而非确定结果。

内容的提问来源于stack exchange,提问作者xmh0511

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 08:28:22