C+是否允许重新订购门店+;好像规则? “IF”规则基本上定义了一个允许在法律C++程序上执行的转换。简而言之,所有不影响程序的可观察行为的转换都是允许的

C+是否允许重新订购门店+;好像规则? “IF”规则基本上定义了一个允许在法律C++程序上执行的转换。简而言之,所有不影响程序的可观察行为的转换都是允许的,c++,c++11,as-if,C++,C++11,As If,至于“可观察的行为”究竟代表什么,似乎与标准给出的关于输入/输出的定义不同。我不确定这是对标准的重新解释,还是一个错误 cppreference.com的“仿佛”规则: 所有输入和输出操作都以相同的顺序进行,并且具有 内容与程序以书面形式执行时的内容相同 标准中的“仿佛”规则: 交互设备的输入和输出动态应发生 以这样一种方式,提示输出实际上是在 程序等待输入。构成交互设备的是 实现定义 这种差异对我来说很重要,因为我想知道正常的存储重新排序是否是有效的编译器优化。按照cppreferen

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

cppreference.com的“仿佛”规则:

  • 所有输入和输出操作都以相同的顺序进行,并且具有 内容与程序以书面形式执行时的内容相同
标准中的“仿佛”规则:

  • 交互设备的输入和输出动态应发生 以这样一种方式,提示输出实际上是在 程序等待输入。构成交互设备的是 实现定义
这种差异对我来说很重要,因为我想知道正常的存储重新排序是否是有效的编译器优化。按照cppreference的说法,内存存储应该属于它提到的
输出操作。但根据标准,内存存储似乎不是交互式设备的输出动态。(什么是交互设备?)

这是一个值得效仿的例子

int A = 0;
int B = 0;

void foo()
{
    A = B + 1;              // (1)
    B = 1;                  // (2)
}
用于函数
foo
的现代编译器:

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

如图所示,存储到
A
将与存储到
B
一起重新排序。它是否符合“似乎”规则?标准是否允许这种重新排序?

标准§1.9/8中给出了“仿佛”规则的真正含义:

  • 对易失性对象的访问严格按照抽象机器的规则进行评估
  • 在程序终止时,写入文件的所有数据应与以下可能结果之一相同: 根据抽象语义执行程序会产生错误
  • 交互设备的输入和输出动态应以如下方式进行: 输出实际上是在程序等待输入之前交付的。什么构成交互设备 是否定义了实现

<> > <>代码> <代码> >代码> b>代码>不允许,此重新排序是允许的。

如果CPuaseNeC.com不符合C++标准的实际文本,CPAPPROCENCE.COM是错误的。唯一可以取代标准文本的是标准的较新版本,以及(有时会汇总到称为“技术勘误表”的文件中,这是标准小版本的一个别致名称)

然而,在本例中,您误解了cppreference.com所说的“输入和输出操作”的含义。(如果内存可用,则该文本将逐字从较旧版本的标准中获取。)存储到内存的是而不是输出操作。在本规则中,只有写入文件(即任何
stdio.h
iostream
输出流,或其他实现定义的机制,例如Unix文件描述符)才算作输出


C和C++标准在2011次修订之前,假设了一个单线程抽象机器,因此不必指定关于存储顺序的任何东西,因为没有办法从程序顺序中观察商店。作为新的多线程规范的一部分,C++11添加了一整套商店订购规则。

+1但是
intx,y;x=3;x=4;y=x
如果使用
x=4
x=3
重新排序,则后者将观察到
y=x
,即使在单线程抽象机器上也是如此。我知道它是哑的,但根据“如果”规则,无论标准对同一内存位置的修改顺序有何要求,它都是有效的?@EricZ if
y
被发送到输出设备(例如,对于
std::cout@Cubbi,我很好奇的是,修改顺序不被视为“仿佛”规则的
可观察行为之一。因此,编译器用
x=4
x=3
进行重新排序是合法的,这没有任何意义。有趣吗?@EricZ
int main(void){int x,y;x=3;x=4;y=x;printf(“%d%d\n”,x,y);返回0;}
必须打印
4
并成功退出。似乎规则意味着编译器可以发出任何它喜欢的机器指令序列,只要它们具有这些效果。特别是,将两个存储交换到
x
将导致程序打印
3
,因此将被禁用错误。@EricZ然而,
intmain(void){intx,y;x=3;x=4;y=x;返回0;}
没有依赖于
x
y
的可观察效果,因此编译器可以自由地对其执行任何操作:特别是,它可以自由地不为任何对象发出代码,但
返回0;
这是大多数现代编译器都会出现的情况,只要您启用优化。”(到底什么是交互设备?)“那些是”在程序等待输入之前提示输出实际上被传递”是一个东西。控制台。