1.lambda表达式使用

lambda表达式又称为匿名表达式,[]存储lambda表达式要捕获的值,()内的参数为形参,可供外部调用传值。lambda表达式可以直接调用:

  • 直接调用:

   [](string name)
   {
       cout << "this is anonymous" << endl;
       cout << "hello " << name << endl;
   }("zack");
  • 通过auto初始化一个变量存储lambda表达式

 auto fname = [](string name)
   {
       cout << "this is auto  " << endl;
       cout << "hello " << name << endl;
   };

   fname("Rolin");
  • 函数指针的方式接受lambda表达式

typedef void (*P_NameFunc)(string name);
// 3 函数指针
P_NameFunc fname2 = [](string name)
{
    cout << "this is P_NameFunc " << endl;
    cout << "hello " << name << endl;
};

fname2("Vivo");
  • function对象接受lambda表达式

   function<void(string)> funcName;
    funcName = [](string name)
    {
        cout << "this is function " << endl;
        cout << "hello " << name << endl;
    };

    funcName("Uncle Wang");

2.lambda的捕获

  • 值捕获

int age = 33;
string name = "zack";
int score = 100;
string job = "softengineer";
//值捕获
[age, name](string name_)
{
    cout << "age is " << age << " name is " << name << " self-name is " << name_ << endl;
}("Novia");

lambda表达式捕获了age和name,是以值的方式来捕获的。所以无法在lambda表达式内部修改age和name的值,如果修改age和name,编译器会报错,提示无法修改const常量,因为age和name是以值的方式被捕获的。

  • 引用捕获

int age = 33;
string name = "zack";
int score = 100;
string job = "softengineer";
[&age, &name](string name_)
{
    cout << "age is " << age << " name is " << name << " self-name is " << name_ << endl;
    name = "Xiao Li";
    age = 18;
}("Novia");

C++的lambda表达式虽然可以捕获局部变量的引用,达到类似闭包的效果,但不是真的闭包,golang和python等语言通过闭包捕获局部变量后可以增加局部变量的声明周期,C++无法做到这一点,所以下面的调用会出现崩溃。

vector<function<void(string)>> vec_Funcs;
void use_lambda2()
{
    int age = 33;
    string name = "zack";
    int score = 100;
    string job = "softengineer";

    vec_Funcs.push_back([age, name](string name_)
                        {   cout << "this is value catch " << endl;
                            cout << "age is " << age << " name is " << name << " self-name is " << name_ << endl; });
    //危险,不要捕获局部变量的引用
    vec_Funcs.push_back([&age, &name](string name_)
                        {   cout << "this is referenc catch" << endl;
                            cout << "age is " << age << " name is " << name << " self-name is " << name_ << endl; });
}

void use_lambda3()
{
    for (auto f : vec_Funcs)
    {
        f("zack");
    }
}

int main(){
    use_lambda2();
    use_lambda3();
}

use_lambda2中将lambda表达式存储在function类型的vector里,当use_lambda2结束后,里边的局部变量都被释放了,而vector中的lambda表达式还存储着局部变量的引用,在调用use_lambda3时调用lambda表达式,此时访问局部变量已经被释放了,所以导致程序崩溃。

  • 全部用值捕获,声明部分变量用引用捕获

int age = 33;
string name = "zack";
int score = 100;
string job = "softengineer";
[=, &name]()
{
    cout << "age is " << age << " name is " << name << " score is " << score << " job is " << job << endl;
    name = "Cui Hua";
}();

通过=表示所有变量都以值的方式捕获,如果希望某个变量以引用方式捕获则单独在这个变量前加&。

  • 全部用引用捕获,声明部分变量用值捕获

int age = 33;
string name = "zack";
int score = 100;
string job = "softengineer";
[&, name]()
{
     cout << "age is " << age << " name is " << name << " score is " << score << " job is " << job << endl;
}();