已更新,见下文!
我听说并读到 C++0x 允许编译器为以下代码段打印Hello"
#include <iostream> int main() { while(1) ; std::cout << "Hello" << std::endl; }
它显然与线程和优化能力有关.不过在我看来,这会让很多人感到惊讶.
有人对为什么有必要允许这样做有很好的解释吗?作为参考,最新的 C++0x 草案在 6.5/5
一个循环,在 for 语句的情况下,在 for-init-statement 之外,
A loop that,outside of the for-init-statement in the case of a for statement,
- 不调用库 I/O 函数,并且
- 不访问或修改易失性对象,并且
- 不执行同步操作 (1.10) 或原子操作(第 29 条)
可能由实现假设终止.[注意:这是为了允许编译器转换即使无法证明终止,也可以删除空循环.— 尾注 ]
这篇富有洞察力的文章介绍了该标准文本
不幸的是,没有使用未定义行为"这个词.然而,每当标准说编译器可以假设 P"时,就暗示具有非 P 属性的程序具有未定义的语义.
Unfortunately,the words "undefined behavior" are not used. However,anytime the standard says "the compiler may assume P," it is implied that a program which has the property not-P has undefined semantics.
是否正确,是否允许编译器为上述程序打印Bye"?
这里有一个更有见地的线程,这是对 C 的类似更改,由 Guy 开始,完成了上面链接的文章.在其他有用的事实中,他们提出了一个似乎也适用于 C++0x 的解决方案(更新:这将不再适用于 n3225 - 见下文!)
endless: goto endless;
似乎不允许编译器将其优化掉,因为它不是循环,而是跳转.另一个人总结了 C++0x 和 C201X 中提议的更改
通过编写一个循环,程序员断言要么循环执行一些可见行为(执行 I/O,访问volatile 对象,或执行同步或原子操作),或它最终终止.如果我违反了那个假设通过编写一个没有副作用的无限循环,我在撒谎编译器,我的程序的行为是未定义的.(如果我幸运的话,编译器可能会警告我.)该语言不提供(不再提供?)一种表达无限循环的方法,而无需可见的行为.
By writing a loop,the programmer is asserting either that the loop does something with visible behavior (performs I/O,accesses volatile objects,or performs synchronization or atomic operations),or that it eventually terminates. If I violate that assumption by writing an infinite loop with no side effects,I am lying to the compiler,and my program's behavior is undefined. (If I'm lucky,the compiler might warn me about it.) The language doesn't provide (no longer provides?) a way to express an infinite loop without visible behavior.
<小时>
2011 年 1 月 3 日更新 n3225:委员会将文本移至 1.10/24 并说
Update on 3.1.2011 with n3225: Committee moved the text to 1.10/24 and say
该实现可能假设任何线程最终都会执行以下操作之一:
The implementation may assume that any thread will eventually do one of the following:
- 终止,
- 调用库 I/O 函数,
- 访问或修改易失性对象,或
- 执行同步操作或原子操作.
goto 技巧将不再工作!