第十七章、C++11的新特性

1. Lambda 表达式

lambda表达式(又叫匿名函数),是C++11标准后新增加的用来创建并返回一个函数的一个表达式。它允许程序在运行时创建函数并返回。

lambda表达式用于在需要的地方创建函数并作为表达式返回,避免在其他地方定义在此调用,可以使程序更易于理解。

语法

捕获列表-> 返回类型 { 函数体 }

说明

  1. 捕获列表决定外部变量如何被 lambda 表达式使用(值捕获、引用捕获等)。
  2. 形式参数列表 同普通函数的形式参数列表一样,是用来定义接收数据的形参变量的列表。
  3. ->返回类型 是此函数的返回类型,可省略。如省略则由 return 后的表达式自动推导得到。

捕获列表的写法

写法
说明
[]
不使用外部的变量。
[&]
引用使用外部的变量(可修改)。
[=]
只读使用外部的变量(不可修改)。
[=,&y]
混合使用外部的变量。

示例

向 copy_if 模版函数中传递 lambda 表达式创建的函数。

// filename: lambda.cpp
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

// 如果是val为负数则返回 true
bool is_negative(const int & val) {
    return val < 0;
}
int main(int argc, char * argv[]) {
    std::vector<int> v{3, -4, 2, -8, 15, 267};
    std::vector<int> v_nega1; // 存放负数的容器
    std::vector<int> v_nega2;

    // 打印 v
    for(auto val: v) 
        cout << val << " ";
    cout << endl;

    // 使用 is_negative 函数筛选出所有的负数
    copy_if(v.begin(),
            v.end(),
            back_inserter(v_nega1), // 末尾插入
            is_negative);

    // 打印 v_nega1;
    cout << "筛选出来负数有:" << endl;
    for(auto val: v_nega1) 
        cout << val << " ";
    cout << endl;
    // 使用 lambda 表达式 筛选出所有的负数
    copy_if(v.begin(),
            v.end(),
            back_inserter(v_nega2), // 末尾插入
            [](const int &val)->bool{return val < 0;});
    // 打印 v_nega2;
    cout << "筛选出来负数有:" << endl;
    for(auto val: v_nega2) 
        cout << val << " ";
    cout << endl;

    return 0;
}

编译和运行结果如下

weimz@mzstudio:~$ g++ -o lambda lambda.cpp
weimz@mzstudio:~$ ./lambda 
3 -4 2 -8 15 267 
筛选出来负数有:
-4 -8 
筛选出来负数有:
-4 -8 

示例2

在 Lambda 表达式内使用外部的变量。

// filename: lambda2.cpp
#include <iostream>
#include <algorithm>

using namespace std;

int main(int argc, char * argv[]) {
    int x = 100;
    int y = 200;

    auto f1 = [=, &y](int a, int b) {
        cout << x + a + b + y << endl;
        y = 6666;
        return x;
    };

    cout << f1(10, 20) << endl;
    cout << "x:" << x << endl;
    cout << "y:" << y << endl;

  return 0;
}

编译和运行结果如下:

weimz@mzstudio:~$ g++ -o lambda2 lambda2.cpp
weimz@mzstudio:~$ ./lambda2 
330
100
x:100
y:6666

可见通过捕获列表 [=,&y] 在 lambda 表达式内可以使用 xy 这两个外部的变量,并可以在 lambda 表达式内修改 y 这个变量。

练习

将下列数组按绝对值排序。

std::vector<int> v{3, -4, 2, -8, 15, 26;

按绝对值升序排序结果。

2, 3, -4, -8, 15, 26;