web-dev-qa-db-ja.com

ラムダ関数でのキャプチャと引数の受け渡しの違い

ラムダ関数とc ++ 11でのその目的は理解していますが、「値の取得」と「引数の受け渡し」の違いはわかりません。例えば..

#include <iostream>
#include <functional>
using namespace std;

int add(int a,int b){
    return a+b;
}

int main(int argc, char** argv){

    function <int(int,int)> cppstyle;
    cppstyle = add;

    auto l = [] (function <int(int,int)> f,int a, int b) {return f(a,b);};

    cout << l(cppstyle,10,30) <<"\n";   
}

上記のコードの出力は、以下のコードと同じです。

#include <iostream>
#include <functional>
using namespace std;

int add(int a,int b){
    return a+b;
}

int main(int argc, char** argv){

    function <int(int,int)> cppstyle;
    cppstyle = add;

    auto l = [cppstyle] (int a, int b) {return cppstyle(a,b);};

    cout << l(10,30) <<"\n";    
}

「値の取得」は「値を引数として渡す」のと同じですか?またはキャプチャには特別な意味がありますか?

25
A_R_P_A

捕らえられた引数と引き渡される引数の違いは、類推で見ることができます。次の関数オブジェクトについて考えてみます。

_struct Capture {
  int &i;
  int const j;
public:
  Capture(int &_i, int &_j) : i(_i), j(_j) {}
  int operator()(int const a, int const b) {
    i *= j;
    return a * b;
  }
};
_

関数オブジェクトクラスCaptureには、2つのメンバー変数ijがあります。 2つの入力引数を取るオーバーロードされたoperator()もあります。次のラムダを考えてみましょう:

_int i, j;
[&i, j](int const a, int const b) {
  i *= j;
  return a * b;
};
_

クラスCaptureのメンバー変数は、ラムダキャプチャ(つまり、_[&i, j]_)と類似していますが、オーバーロードされたoperator()aおよびbは、上記のラムダの入力引数aおよびbと類似しています。

つまり、ラムダを関数オブジェクトと見なす場合、そのキャプチャは関数オブジェクト(つまり、そのメンバー変数)の状態ですが、その入力引数はオーバーロードされたoperator()の入力引数になります。

21
101010

より高いレベルでは、現在知っているデータをキャプチャし、電話をかける必要があるまで持っていないデータを渡します。

たとえば、ベクトル内のすべての数値に定数を追加したいとします。次のように書くことができます(注意:未テスト):

void Add(std::vector<int>& v, int i)
{
    std::for_each(std::begin(v), std::end(v), [i](int& j){ j += i; });
}
15
Nevin

I値のキャプチャは、ラムダが定義されたときに設定されますが、iが引数(j)として渡されると、ループ内で変化します。

#include <iostream>
using namespace std;

int main(int argc,char **argv)   {
    auto i=5;
    auto f = [=](int j) {cout<<"capture i="<<i<<", passing i as j="<<j<< endl; };
    while (i<30) {
        i += 10;
        f(i);
    }
}

---これは出力になります:

ラムダキャプチャi = 5、iを引数j = 15として渡す

ラムダキャプチャi = 5、引数j = 25としてiを渡す

ラムダキャプチャi = 5、引数j = 35としてiを渡す

0
Raul1962