私はこのコードを持っています:
int i = 0;
[&i](){i++;}();
しかし、私は i を省略して使用することができます:
[&](){i++;}();
を指定する目的は何&i
ですか? (および同様に=var
および=
)。コンパイル時間や実行時のパフォーマンスに影響はありますか?
&i
参照としてのみi
キャプチャされることを&
意味し、ラムダで使用されるすべての変数がスコープからキャプチャされることを意味します。
int i = 0, j = 10;
[&i]{ i++; j++;}(); //error: j is not captured by reference
[&]{ i++; j++;}(); //ok: both variables are captured by reference
この&i
アプローチは、キャプチャされた変数の量を制限するために言語によって提供されます。C++ では、キャプチャする特定の変数、キャプチャする方法 (値または参照による) に関して、キャプチャされた変数を完全に制御できます。
i
および と同じ理由=
:
int i = 0, j = 10;
[i]{ i++; j++;}(); //error: j is not captured (only i is captured by value)
[=]{ i++; j++;}(); //ok: both variables are captured by value
//more
[&i, j]{ i++; j++;}(); //ok: captured i by reference, j by value
それが役立つことを願っています。
さまざまな変数をさまざまな方法でキャプチャしたい場合があります。
std::vector<int> v { 7, 8, 9, 10, 11 };
int n = 3;
//Capture v by reference and n by value:
auto getNth = [&v, n](){ return v[n]; };
//Behavior:
n = 9999;
getNth(); //returns 10 - changing n didn't affect the lambda
v[3] = 42;
getNth(); //returns 42 - changing v did affect the lambda
これが、より詳細な構文が使用できる理由です。
この機能はパフォーマンスではなく、読みやすさと保守性に関するものです。ブランケット キャプチャ構文を使用する[&]
と[=]
、元のメソッドとラムダ本体の間で共有される状態がわかりにくくなります。これは、開発者が値がキャプチャされていないと誤って想定している場合、メソッドのメンテナンスの問題に寄与する可能性があります。キャプチャ句があると、ラムダが依存する状態がより明確になります。
&i を指定する目的は何ですか? (同様に =var と =)。コンパイル時間や実行時のパフォーマンスに影響はありますか?
値を参照によってキャプチャするか、値によってキャプチャするかを指定できます。Using[&]
は、参照によってすべてをキャプチャすることを指定しますが、次のことを行うラムダを記述することもできます。
[=, &i, &j]()
これは、キャプチャと参照を除いて、すべてを値でキャプチャすることを意味します。i
j
あなたの特定のケースでは、これは役に立ちません-参照によってすべてをキャプチャすると言うだけで、コンパイラは を使用していると判断し、i
参照によってキャプチャします-しかし、キャプチャされている複数の変数を扱う場合、C++ではそれぞれが個別にキャプチャされる方法を制御します。
キャプチャする変数をリストすると、必要なものが明確になります。また、使用したくないもの (キャプチャしなかったもの) を使用すると、コンパイラ エラーが発生します。これは良いこと (実装で本当にミスを犯した) かもしれませんし、悪いこと (単に変数をリストするのを忘れただけ) かもしれません。
それは実際には特定のシナリオに依存します。ラムダが複雑であるほど、および/または包含スコープが複雑であるほど、キャプチャするものを明示する方が良いと思います。
追加のポイントがあります。それは、値によるキャプチャと参照によるキャプチャを混在させていることです。少なくともそのうちの 1 つを明示する必要があります。例:
int i, j, k;
auto f = [=, &i]() { /* code which can read i, j and k but can only modify i */ };