[解決済み] 末尾再帰最適化を行うC++コンパイラがあるとすれば、どのコンパイラですか?
質問
CとC++の両方で末尾再帰の最適化を行うことは完全にうまくいくように思えますが、デバッグ中にこの最適化を示すフレームスタックを見ることはないようです。スタックを見れば、再帰の深さがわかるので、それはいいことだと思います。しかし、この最適化も同様に素晴らしいものです。
この最適化を行うC++コンパイラはありますか?なぜですか?なぜしないのですか?
どのようにコンパイラに指示すればよいのでしょうか?
-
MSVCの場合。
/O2
または/Ox
-
GCCの場合。
-O2
または-O3
コンパイラがあるケースでこうなっているかどうかをチェックするのはどうでしょうか。
- MSVCの場合、PDB出力を有効にしてコードをトレースできるようにし、コードを検査します。
- GCCの場合は...?
ある関数がコンパイラによってこのように最適化されているかどうかを判断する方法について、提案を受けたいと思います(Konradがそれを想定するように言ってくれるのは心強いですが)。
コンパイラがこのようなことを全くしないかどうかは、無限再帰を行い、無限ループやスタックオーバーフローになるかどうかをチェックすることで常に可能です(私はGCCでこれを行い、以下のことを発見しました。
-O2
で十分なのですが)、どうせ終了することが分かっている特定の関数をチェックできるようにしたいのです。これを簡単にチェックする方法があればいいのですが :)
いくつかのテストの後、私はデストラクタがこの最適化を行う可能性を台無しにすることを発見しました。特定の変数やテンポラリのスコープを変更して、returnステートメントが始まる前にスコープ外になるようにすることは、時として価値があることなのです。
テールコールの後にデストラクタを実行する必要がある場合、テールコールの最適化はできません。
解決方法は?
現在主流のコンパイラはすべてテールコール最適化を行っています。 は、かなりよくできています(10年以上前からできています)。 相互に再帰的な呼び出しであっても のようなものです。
int bar(int, int);
int foo(int n, int acc) {
return (n == 0) ? acc : bar(n - 1, acc + 2);
}
int bar(int n, int acc) {
return (n == 0) ? acc : foo(n - 1, acc + 1);
}
コンパイラに最適化をさせるのは簡単です。高速化のための最適化をオンにするだけです。
-
MSVCの場合は
/O2
または/Ox
. -
GCC、Clang、ICCの場合は、以下のようになります。
-O3
コンパイラが最適化を行ったかどうかを確認する簡単な方法は、スタックオーバーフローになるような呼び出しを行うこと、またはアセンブリ出力を見ることです。
興味深い歴史的なメモとして、C言語のテールコール最適化がGCCに追加されたのは 卒業論文 マーク・プロブスト氏によるものです。この論文には、実装上の興味深い注意点がいくつか書かれています。一読の価値ありです。
関連
-
[解決済み] error: 'ostream' does not name a type.
-
[解決済み】変数 '' を抽象型 '' と宣言できない。
-
[解決済み】デバッグアサーションに失敗しました。C++のベクトル添え字が範囲外
-
[解決済み】'std::cout'への未定義の参照
-
[解決済み] SQLiteのINSERT/per-secondのパフォーマンスを向上させる
-
[解決済み] 末尾再帰とは何ですか?
-
[解決済み] テールコール最適化とは何ですか?
-
[解決済み] 8192個の要素にループをかけると、プログラムが遅くなるのはなぜですか?
-
[解決済み] どちらが速いですか?スタックアロケーションとヒープアロケーション
-
[解決済み】静的定数文字列(クラスメンバ)
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] テスト
-
[解決済み】文字列関数で'char const*'のインスタンスを投げた後に呼び出されるterminate [閉店].
-
[解決済み】C++の変数はイニシャライザーを持っているが、不完全な型?
-
[解決済み】エラー:strcpyがこのスコープで宣言されていない
-
[解決済み】オブジェクト引数のない非静的メンバ関数の呼び出し コンパイラーエラー
-
[解決済み】クラステンプレートの使用にはテンプレート引数リストが必要です
-
[解決済み】エラー:free(): 次のサイズが無効です(fast)。
-
[解決済み】クラスのコンストラクタへの未定義参照、.cppファイルの修正も含む
-
[解決済み】デバッグアサーションに失敗しました
-
[解決済み] 変数サイズのオブジェクトが初期化されないことがある c++