C++11 Lambda表达式与匿名函数

lambda表达式是C++11中最重要的新特性之一,而Lambda表达式,实际上就是提供了一个类似匿名函数的特性,而匿名函数则是在需要一个函数,但是又不想费力去命名一个函数的情况下去使用的。这样的场景其实有很多很多,所以匿名函数几乎时现代编程语言的标配。

基础语法

Lambda表达式的基础语法如下:

返回值 = [捕获参数](传入参数列表)mutable(可选)异常属性 -> 返回类型{
    //函数体
}(传入参数并开始执行,无参数,则为空);//传入参数为空();


auto a = [捕获参数](传入参数列表)mutable(可选)异常属性 -> 返回类型{
    //函数体
}(传入参数并开始执行,无参数,则为空);//传入参数为空();
a(传入参数);//调用
  • Lambda表达式以一对中括号开始
  • 有参数列表
  • 有函数体,会有return语句
  • 一般不需要说明返回值类型(auto),有特殊情况需要说明时,应使用箭头语法的方式
  • 每个lambda表达式都有一个全局唯一的类型,要精确捕捉lambda表达式到一个变量中,只能通过auto声明的方式
#include <iostream>
using namespace std;

int main()
{
   int c =  [](int a, int b) ->int {
        return a+b;
  }(1, 2);
  cout << c << endl;
    system("pause");
    return 0;
}

结果等于3

函数保存

auto f =  [](int a, int b) -> int {return a+b;}
auto c = f(1,2);

捕获列表与mutable

  • 对参数只读
#include <iostream>
using namespace std;

int main()
{
    int i = 10;
   int c =  [i](int a, int b) ->int {
        return a+b+i;
  }(1, 2);
  cout << c << endl;
    system("pause");
    return 0;
}
  • 对参数读写
#include <iostream>
using namespace std;

int main()
{
    int i = 10;
   int c =  [i](int a, int b) ->int {
       i++;
        return a+b+i;
  }(1, 2);
  cout << c << endl;
    system("pause");
    return 0;
}
error: increment of read-only variable 'i'
  • mutable
  • mutable实际上对原参数在子函数中的一种复制(按值传递)成为一个局部变量。未改变源参数的值
#include <iostream>
using namespace std;

int main()
{
    int i = 10;
   auto f =  [i](int a, int b)mutable ->int {
       i++;
       return a+b+i;
       };
  cout << "c = " << f(1,2) << endl;
  cout << "c = " << f(1,2) << endl;
  cout << "i = " << i << endl;
    system("pause");
    return 0;
}

结果如下

c = 14
c = 15
i = 10
  • 如果想修改原参数的值,可以通过引用捕获的方式
#include <iostream>
using namespace std;

int main()
{
    int i = 10;
   auto f =  [&i](int a, int b) ->int {
       i++;
       return a+b+i;
       };
  cout << "c = " << f(1,2) << endl;
  cout << "c = " << f(1,2) << endl;
  cout << "i = " << i << endl;
    system("pause");
    return 0;
}
c = 14
c = 15
i = 12
  • 捕获列表
auto f = [a, b](int c, int d) ->int{
    retrun a+b+c+d;
}
int h = f(1,2);
cout<<h<<endl;
  • 按值捕获所有参数
[=](int a, int b) ->int {
    return a+b;
}
  • 按引用捕获所有参数
[&](int a, int b) ->int {
    return a+b;
}
  • 混用
[a,b,&c,&d] ->int {
    ...
}
  • 类函数中使用-&可以引用传递类内所有数据,包括私有数据
#include <iostream>
#include <string>
class classA
{
private:
    int m_data;
public:
    classA(int data) :m_data(data){};
    int getm_data(){ return m_data; }
    void tryUseClassLambda(void);
};

void classA::tryUseClassLambda(void)
{
    [&] {
        m_data++;
        std::cout << "类内访问参数m_data:" << m_data << std::endl;
    }();//声明完立即调用
    return ;
}
int main()
{
    classA ca(1);
    ca.tryUseClassLambda();
    std::cout << "类外访问参数m_data:" << ca.getm_data() << std::endl;
    system("pause");
    return 0;
}
类内访问参数m_data:2
类外访问参数m_data:2
  • 在类中使用-this可以引用传递类内所有数据,包括私有数据
#include <iostream>
#include <string>
class classA
{
private:
    int m_data;
public:
    classA(int data) :m_data(data){};
    int getm_data(){ return m_data; }
    void tryUseClassLambda(void);
};

void classA::tryUseClassLambda(void)
{
    [this] {
        m_data++;
        std::cout << "类内访问参数m_data:" << m_data << std::endl;
    }();//声明完立即调用
    return ;
}
int main()
{
    classA ca(1);
    ca.tryUseClassLambda();
    std::cout << "类外访问参数m_data:" << ca.getm_data() << std::endl;
    system("pause");
    return 0;
}
类内访问参数m_data:2
类外访问参数m_data:2