更新されました。以下を参照してください。
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」を出力することを許可されていますか?
ここにはさらに洞察に満ちたスレッドがあります。これは、上記のリンクされた記事を行ったGuyによって開始された、Cと同様の変更に関するものです。他の有用な事実の中で、それらはC ++ 0xにも適用されるように見える解決策を提示します(更新:これはn3225ではもう機能しません-以下を参照してください!)
endless:
goto endless;
コンパイラはそれを最適化することを許可されていないようです。なぜなら、それはループではなく、ジャンプだからです。別の男がC++0xとC201Xで提案された変更を要約します
ループを作成することにより、プログラマーは、ループが目に見える動作(I / Oの実行、揮発性オブジェクトへのアクセス、同期またはアトミック操作の実行)で何かを実行するか、 最終的に終了することを表明します。副作用のない無限ループを記述してその仮定に違反した場合、私はコンパイラーに嘘をつき、プログラムの動作は未定義になります。(運が良ければ、コンパイラーはそれについて警告するかもしれません。)この言語は、目に見える振る舞いなしに無限ループを表現する方法を提供していません(もはや提供していませんか?)。
2011年3月1日にn3225で更新:委員会はテキストを1.10 / 24に移動し、次のように述べます。
実装では、任意のスレッドが最終的に次のいずれかを実行すると想定する場合があります。
- 終了、
- ライブラリI/O関数を呼び出します。
- 揮発性オブジェクトにアクセスまたは変更する、または
- 同期操作またはアトミック操作を実行します。
goto
トリックはもう機能しません!