更新,请参见下文!
我听说过,C ++ 0x允许编译器为以下代码段打印“ Hello”
#include <iostream>
int main() {
while(1)
;
std::cout << "Hello" << std::endl;
}
显然,它与线程和优化功能有关。在我看来,这会让很多人感到惊讶。
有人对为什么要允许这样做有很好的解释吗?作为参考,最新的C ++ 0x草案在6.5/5
在for语句的情况下,在for-init-statement之外的循环,
- 不调用库I / O函数,并且
- 不访问或修改易失性对象,并且
- 不执行任何同步操作(1.10)或原子操作(第29条)
实现可能会假定它终止。[注意:这旨在允许编译器进行转换,例如删除空循环,即使无法证明终止也是如此。—尾注]
编辑:
这篇有见地的文章谈到了该标准文本
不幸的是,没有使用“未定义行为”一词。但是,只要该标准说“编译器可以假定P”,就意味着具有not-P属性的程序具有未定义的语义。
这是正确的,并且允许编译器为上述程序打印“ Bye”吗?
这里有一个更具洞察力的线程,它与对C的类似更改有关,由Guy在上面的链接文章中开始。在其他有用的事实中,他们提出了一种似乎也适用于C ++ 0x的解决方案(更新:在n3225上将不再起作用-参见下文!)
endless:
goto endless;
看来,不允许编译器对其进行优化,因为这不是循环,而是跳转。另一个人总结了C ++ 0x和C201X的拟议更改
通过编写一个循环,程序员断言或者环路不可见的东西的行为(执行I / O,访问volatile对象,或进行同步或原子操作), 或者,它最终会终止。如果我通过写一个没有副作用的无限循环违反了这一假设,那我就是对编译器撒谎,而我的程序的行为是不确定的。(如果幸运的话,编译器可能会警告我。)该语言不提供(不再提供?)一种表达无可见行为的无限循环的方法。
在2011年3月31日更新了n3225:委员会将文本移至1.10 / 24并说
该实现可以假定任何线程最终都将执行以下操作之一:
- 终止,
- 调用库I / O函数,
- 访问或修改易失性对象,或
- 执行同步操作或原子操作。
的goto
把戏,不工作了!
int x = 1; for(int i = 0; i < 10; ++i) do_something(&i); x++;
为for(int i = 0; i < 10; ++i) do_something(&i); int x = 2;
?或者可能以另一种方式,将x
其初始化为2
循环之前。它可以告诉您do_something
不在乎的值x
,因此,如果 do_something
不引起值的i
改变而导致最终陷入无限循环,则它是完全安全的优化。
main() { start_daemon_thread(); while(1) { sleep(1000); } }
可能立即退出而不是在后台线程中运行我的守护进程?
while(1) { MyMysteriousFunction(); }
在不知道该神秘函数的定义的情况下必须可以独立编译,对吗?那么我们如何确定它是否对任何库I / O函数进行调用?换句话说:确保第一个项目符号可以表达为不会调用function。