Wang's blog

函数对象与lambda表达式

Published on

函数对象

函数对象(仿函数/函子)指实现了operator()运算符的类的对象,它的调用方式与函数类似。相对于直接函数调用,函数对象有两个优势:

  • 函数对象可包含状态
  • 函数对象是一个类型,因此可用作模板参数
class Plus
{
public:
    int operator()(int a, int b)
    {
        return a + b;
    }
};

int main()
{
    Plus plus;
    int n = plus(11, 22);
}

lambda表达式

lambda表达式是C++11引入的一个语法糖,使用它可以方便快捷地创建一个匿名函数对象。

int main()
{
    auto plus = [](int a, int b) { return a + b; };
    int n = plus(11, 22);
}

组成

一个完整lambda表达式的组成如下:

[ capture-list ] ( params ) mutable(optional) exception(optional) -> ret(optional) { body } 
  • 捕获列表(capture-list)
  • 参数列表(params)
  • mutable标识(mutable,可选)
  • 异常标识(exception,可选)
  • 返回类型(ret,可选)
  • 函数体(body)

其中,参数列表、异常标识、返回类型、函数体4部分都与函数基本相同,其它部分说明如下:

捕获列表

捕获列表使lambda表达式可以访问其所在作用域内的变量,捕获的方式有两种:

  • 按值捕获:访问变量的副本,修改副本不影响原变量
  • 按引用捕获:访问变量的引用,修改引用会修改原变量

这两种捕获方式可以有多种组合:

[]      // 不捕获任何变量
[=]     // 按值捕获所有用到的变量
[&]     // 按引用捕获所有用到的变量
[a]     // 按值捕获变量a
[&b]    // 按引用捕获变量b
[=, &a] // 按引用捕获变量a,按值捕获其它变量
[&, b]  // 按值捕获变量b,按引用捕获其它变量
[a, &b] // 按值捕获变量a,按引用捕获变量b

mutable标识

默认情况下,lambda表达式中值捕获的变量无法修改,如果需要修改,则需指定mutable标识。注意,由于是值捕获,即使可以修改,修改的也是变量的副本,并不影响原变量。