2

as-if ”规则基本上定义了允许实现在合法 C++ 程序上执行的转换。简而言之,所有不影响程序可观察行为的转换都是允许的。

至于“可观察行为”究竟代表什么,cppreference.com似乎与标准给出的定义不同,关于 input/output。我不确定这是对标准的重新解释,还是错误。

cppreference.com 的“ as-if ”规则:

  • 所有输入和输出操作都以相同的顺序和内容发生,就好像程序按照编写的方式执行一样。

标准的“ as-if ”规则:

  • 交互式设备的输入和输出动态应该以这样一种方式发生,即在程序等待输入之前实际交付提示输出。什么构成交互式设备是实现定义的

这种差异对我来说很重要,因为我想知道正常的商店重新排序是否是有效的编译器优化。根据 cppreference 的措辞,内存存储应该属于output operations它所提到的。但根据标准,内存存储似乎不是the output dynamics of interactive devices. (到底什么是交互式设备?)

一个可以效仿的例子。

int A = 0;
int B = 0;

void foo()
{
    A = B + 1;              // (1)
    B = 1;                  // (2)
}

现代编译器可能会为 function生成以下代码foo

mov     0x804a018, %eax
movl    $0x1, 0x804a018    ; store 1 to B
add     $0x1, %eax         
mov     %eax, 0x804a01c    ; store 1 to A
ret

如所见, store toA与 store to 一起重新排序B。它是否符合“ as-if ”规则?标准是否允许这种重新排序?

4

2 回答 2

3

如果 cppreference.com 不同意 C++ 标准的实际文本,则 cppreference.com 是错误的。唯一可以取代标准文本的是标准的较新版本,以及缺陷报告的官方解决方案(有时会汇总到称为“技术勘误”的文档中,这是一个花哨的名称,用于次要版本的标准)。

但是,在这种情况下,您误解了 cppreference.com 所说的“输入和输出操作”是什么意思。(如果有记忆,该文本是从标准的旧版本逐字获取的。)存储到内存不是输出操作。出于此规则的目的,仅写入文件(即任何stdio.hiostream输出流,或其他实现定义的机制,例如 Unix 文件描述符)才算作输出。

C 和 C++ 标准在 2011 年修订之前假定为单线程抽象机,因此没有费心指定任何有关存储顺序的内容,因为无法观察程序顺序之外的存储。作为新的多线程规范的一部分,C(++)11 添加了一大堆存储排序规则。

于 2014-08-14T00:17:20.103 回答
2

标准中的第 1.9/8 节中可以找到 as-if 规则的真正表述:

  • 对 volatile 对象的访问严格按照抽象机的规则进行评估。
  • 在程序终止时,写入文件的所有数据应与根据抽象语义执行程序可能产生的结果之一相同。
  • 交互式设备的输入和输出动态应该以这样一种方式发生,即在程序等待输入之前实际交付提示输出。构成交互式设备的内容是实现定义的。

由于AB不是易失性的,因此允许这种重新排序。

于 2014-08-14T00:14:49.707 回答