“ as-if ”规则基本上定义了允许在合法C ++程序上执行的实现的转换。简而言之,允许所有不影响程序的 可观察行为 的转换。
至于 “可观察行为” 的确切含义,cppreference.com似乎与标准提供的定义不同,关于输入/输出。我不确定这是对标准的重新解释,还是错误。
cppreference.com“ as-if ”规则:
标准的
- 所有输入和输出操作都以相同的顺序发生 相同的内容就像程序按照书面执行一样。
“ as-if ”规则:
- 应进行交互设备的输入和输出动态 以这种方式提示输出实际上是在a之前传递的 程序等待输入。构成交互设备的是什么 实现定义
这种差异对我很重要,因为我想知道正常的商店重新排序是否是有效的编译器优化。根据cppreference的措辞,内存存储应该属于它提到的output operations
。但根据标准,内存存储似乎不是the output dynamics of interactive devices
。 (无论如何,什么是交互式设备?)
要遵循的一个例子。
int A = 0;
int B = 0;
void foo()
{
A = B + 1; // (1)
B = 1; // (2)
}
功能foo
的现代编译器may generate the following code:
mov 0x804a018, %eax
movl $0x1, 0x804a018 ; store 1 to B
add $0x1, %eax
mov %eax, 0x804a01c ; store 1 to A
ret
如图所示,A
的商店与商店重新排序为B
。它是否符合“ as-if ”规则?标准是否允许这种重新排序?
答案 0 :(得分:3)
如果cppreference.com不同意C ++标准的实际文本,则cppreference.com是错误的。唯一可以取代标准文本的是标准的更新版本,official resolutions of defect reports(有时会被卷入称为“技术corrigienda”的文档中,这是一个很小的版本标准)。
但是,在这种情况下,您误解了“输入和输出操作”对cppreference.com的意义。 (如果内存服务,该文本将从标准的旧版本逐字逐句获取。)内存存储为 NOT 输出操作。只写入文件(即任何stdio.h
或iostream
输出流,或其他实现定义的机制,例如Unix文件描述符)计为输出这个规则。
C和C ++标准在2011年版本之前,假定是一个单线程抽象机器,因此没有任何关于商店订购的说明,因为没有办法观察商店程序顺序。作为新的多线程规范的一部分,C(++)11为商店排序添加了一大堆规则。
答案 1 :(得分:2)
as-if规则的真实表述见标准中的§1.9/ 8:
- 严格按照抽象机的规则评估对volatile对象的访问。
- 在程序终止时,写入文件的所有数据应与其中一个可能的结果相同 根据抽象语义执行程序会产生。
- 交互设备的输入和输出动态应以提示的方式进行 输出实际在程序等待输入之前传送。什么构成了交互设备 是实现定义的。
由于A
和B
不易变,因此允许重新排序。