2012-01-31 9 views
0

ラムダをクラスメンバとして格納して呼び出しを延期できるようにする必要がある場合に使用するベストプラクティスは何ですか?より具体的には、以下のコードリストのクラスdeferred_lambdaに渡されたラムダを参照として格納することは安全ですか?そうでない場合は、参照としてではなく値としてdeferred_lambdaにラムダを格納することは安全でしょうか?クラスにラムダを格納する

最後に、このようにラムダをクラスメンバーとして格納するg ++の通常の関数呼び出しと比較して、パフォーマンス上のペナルティが発生すると予想できますか?つまり、deferred_lambda.invoke()を使用すると、同じ操作を実装するいくつかのダミー構造体のoperator()への呼び出しよりも遅くなるでしょうか?

g ++では、キャプチャされた変数を多く使うほどラムダのサイズが大きくなることに気付きました。これは私の理解によれば、コンパイラはメンバーとして必要なキャプチャされた変数を含むラムダの構造体を内部的に生成するので、これが期待されると思います。この見解は、ラムダを値で保存することは、参照を保存するよりも時間とメモリの面で高価になる可能性があるため、今質問している質問につながったのです。

template <class Func> 
class deferred_lambda 
{ 
    Func& func_; 
public: 
    deferred_lambda(Func func) : func_(func) {} 
    void invoke() { func_(); } 
}; 

template <class Func> 
deferred_lambda<Func> defer_lambda(Func func) 
{ 
    return deferred_lambda(func); 
} 

void foo() 
{ 
    int a, b, c; 
    auto x = defer_lambda([&]() { a = 1; b = 2; c = 3; }); 
} 
+0

なぜ関数オブジェクトに_reference_を格納するのかわかりません。 –

+0

'は、同じ操作を実装するいくつかのダミー構造体でoperator()を呼び出すよりも、deferred_lambda.invoke()を使用するほうが遅くなるでしょうか?それは、とにかくlambda _is_です。 –

+0

私の質問では、より多くのキャプチャ変数が使用されるにつれて、関数オブジェクトが大きくなる可能性があります。 –

答えて

4

具体的には、参考として以下のコードリストのクラスdeferred_lambdaに渡されるラムダを格納するために安全ですか?

いいえdefereed_lambda()が終了した後、それはぶら下がりの参照になります。

もし私がリファレンスとしてではなく値としてdeferred_lambdaにラムダを格納するのであれば安全でしょうか?

はい。しかし、ラムダを実行するときに参照によって捕捉された変数がまだ生存していることを確認する必要があります。

つまり、deferred_lambda.invoke()は、同じ操作を実装するいくつかのダミー構造体のoperator()呼び出しよりも遅くなるでしょうか?

おそらくそうではありません。

この観測は、でしょう、それらへの参照を保存するよりも時間の面で高価とメモリであってもよい値でラムダを格納するので、私が今求めています質問につながったものです。

それはまだ私が後で実行するためにラムダを保存する方法はstd::functionオブジェクトを使用することであると考えている...どこかを保存する

7

を持っています。ライブラリの実装によっては、functionクラスに必要なコンストラクタとコンバーターにラムダ、または他の種類のファンクタまたは関数が後で実行するために割り当てられる必要があります。

関連する問題