更新されました、以下を参照してください!
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プロパティを持つプログラムはセマンティクスが未定義であることを意味します。
それは正しいですか、コンパイラは上記のプログラムの「バイ」を出力することを許可されていますか?
ここにはさらに洞察に満ちたスレッドがあります。これはCへの類似の変更に関するもので、上記のリンクされた記事を書いた人によって開始されました。他の有用な事実の中で、それらはC ++ 0xにも適用されると思われる解決策を提示します(更新:これはn3225ではもう機能しません-下記を参照してください!)
endless:
goto endless;
コンパイラはループではなくジャンプなので、それを最適化することはできません。別の男はC ++ 0xとC201Xで提案された変更を要約します
ループを書き込むことによって、プログラマがアサートされているいずれかのループは、可視挙動を有するもの(実行I / O、アクセス揮発性オブジェクト、または実行同期または原子操作)をしていること、 またはそれが最終的に終了すること。副作用のない無限ループを作成してその仮定に違反すると、コンパイラーに嘘をついてしまい、プログラムの動作は未定義になります。(運が良ければ、コンパイラーが警告するかもしれません。)この言語は、目に見える動作なしで無限ループを表現する方法を提供していません(提供していませんか?)。
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関数を呼び出すかどうかをどのように判断できますか?言い換えれば、最初の箇条書きを確実にフレーズできるのは、関数を呼び出さないということです。