绝对地。
由于x
没有标记为volatile
并且看起来是一个具有自动存储时长和内部链接的本地对象,并且程序没有对其进行修改,因此这两个程序是等价的。
在 C++03 和 C++11 中,这是 as-if 规则,因为访问非易失性对象不被视为程序的“副作用”:
[C++11: 1.9/12]:
访问由 volatile glvalue (3.10) 指定的对象、修改对象、调用库 I/O 函数或调用执行任何这些操作的函数都是副作用,它们是执行环境状态的变化。表达式(或子表达式)的评估通常包括值计算(包括确定对象的身份以进行左值评估和获取先前分配给对象以进行纯右值评估)和副作用的启动。当对库 I/O 函数的调用返回或对 volatile 对象的访问被评估时,副作用被认为是完整的,即使调用(例如 I/O 本身)或 volatile 访问隐含的一些外部操作可能还没有完成。
C++11 确实为全局对象腾出了空间,可以在一个线程中更改其值,然后在另一个线程中读取新值:
[C++11: 1.10/3]:
T
根据以下规则,在特定点对线程可见的对象的值是对象的初始值、分配给对象T
的值或由另一个线程分配给对象的值。
但是,如果您这样做,因为您的对象不是原子的:
[C++11: 1.10/21]:
如果程序的执行包含不同线程中的两个冲突操作,则该程序的执行包含数据竞争,其中至少一个不是原子的,并且两者都不会在另一个之前发生。任何此类数据竞争都会导致未定义的行为。
而且,当调用未定义的行为时,任何事情都可能发生。
引导笔记
[C++11: 1.10/25]:
实现应确保由原子或同步操作分配的最后一个值(按修改顺序)将在有限的时间段内对所有其他线程可见。
再次注意,对象必须是原子的(例如std::atomic<bool>
)才能获得此保证。