2016-03-20 2 views
-3

ラムダが状態を保存しなければならない場合、インライン化されない可能性があります。状態が保存されていない場合は、単純なフリー関数のようになり、インライン化される可能性が高くなります。ラムダはインライン化の機会が多い

標準はそれについて何か言いますか? LLVMの上に行くためのコンパイラを書く過去数年間、私の暇な時間の多くを費やしてきた誰かとして

class Window {public:int value = 5;}; 

class SomeClass: 
{ 
public: 
    Window *w; 

    void DoSomething() 
    { 
     auto error = [&](int n) 
     { 
      std::cout << (w->value * 5); 
      return w->value * n; 
     }; 

     auto error = [](Window *w, int n) 
     { 
      std::cout << (w->value * 5); 
      return w->value * n; 
     }; 

     error(w, 7); 
     error(7); 
     // ... 

     error(w, 10); 
     error(10); 

    } 
} 
+0

@CaptainObvlious私は、標準がそれについて何かを言うかどうか尋ねました。私が知る限り、この標準は異なるコンパイラに依存していません。 – James

+1

コンパイラにインライン展開に問題がある場合は、バグを報告してください。 –

+0

"*スタンダードはそれについて何か言いますか?*"いいえ、それはありません。 'inline'宣言されていないインライン関数は完全にインプリメンテーションに依存します(インライン関数はインライン関数でもインプリメンテーションに依存しますが、少なくとも標準ではインライン関数の可能性を認識しています)。 – Cornstalks

答えて

1

、私はまともなコンパイラがこれらの両方をインラインますかなり確信している - そうでない場合は、I誰もコンパイラを作ってくれない人にはバグを起こします。

[...]の要素は、通常、構造体へのポインタ(関数がインライン化されている場合は通常の引数に "unpicked"することができます)に変わる余分な引数(クロージャ引数)になります。

単純な小さな関数がインライン化されない主な理由は、vtableを含む関数ポインタを通じて呼び出されることです。コンパイラーは関数が他の場所で呼び出されていないと判断できないため、非インラインバージョンでは非静的[グローバルレベルで]関数が生成されることもあります。

もちろん、LARGE関数はインライン化されない可能性があります。これは、コンパイラがそれを実行するためのスペースが無駄だと考えているからです。しかしgccは、例えば、ある場所からしか知りません。

コンパイラがラムダを他の関数にインライン展開する方法に違いはないと主張します - ラムダが関数から渡されない限りどこからでも明示的に呼び出すことはできませんstd :: functionなどと宣言されていますが、いずれにしてもインライン化することはできません。

本当に気にしたら、コンパイラの出力を確認してください。

+0

私はこの問題を理解しようと最後の30分を費やしました。 http:// ideone。com/UaJG7Yこの問題により、ラムダ本体の機能が長すぎて、リリースモードでインライン化できませんでした。その行動に関するアイディアですか?それとも単に私が報告すべき視覚的なスタジオバグですか? – James

+0

'va_arg'関数はインライン化できません。仕様ではそうは言えないかもしれませんが、私はまだそれを扱うコンパイラを見たことがありません。これは、可変数の引数では、引数がスタックに渡されるため(典型的な場合)、通常は正しいスタッククリーンアップをインライン化できないためです。 –

+0

(私は嘘をついています - 私はOpenCLコンパイラを仕事中のインラインprintfで見たことがありますが、printfを同じ時間で12回呼び出すとコンパイル時間が非常に長くなる1行~3000行のprintfを数回インライン展開すると、コンパイラのパフォーマンスにはあまり適していません) –

関連する問題