跳转到内容

C++11 Lambda 表达式

来自代码酷

C++11 Lambda表达式[编辑 | 编辑源代码]

简介[编辑 | 编辑源代码]

Lambda表达式是C++11引入的一项重要特性,它允许在代码中定义匿名函数对象(也称为闭包)。Lambda表达式提供了一种简洁的方式来创建临时函数,特别适用于需要传递函数作为参数的场景(如STL算法、回调函数等)。与传统的函数指针和函数对象相比,Lambda更加灵活且语法更简洁。

Lambda表达式的主要特点包括:

  • 可以捕获上下文变量
  • 支持内联定义
  • 自动推导返回类型(或在某些情况下显式指定)
  • 可作为参数传递或存储在变量中

基本语法[编辑 | 编辑源代码]

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

[捕获列表](参数列表) -> 返回类型 {
    // 函数体
}

其中:

  • 捕获列表:指定哪些外部变量可以在Lambda体内使用,以及如何捕获它们(值捕获或引用捕获)
  • 参数列表:与普通函数的参数列表类似
  • 返回类型:可以省略(编译器自动推导),但在某些情况下需要显式指定
  • 函数体:包含Lambda执行的代码

最简单的Lambda示例[编辑 | 编辑源代码]

#include <iostream>

int main() {
    // 定义一个简单的Lambda,不捕获任何变量,无参数
    auto greet = []() {
        std::cout << "Hello, Lambda!" << std::endl;
    };
    
    // 调用Lambda
    greet();
    
    return 0;
}

输出:

Hello, Lambda!

捕获列表详解[编辑 | 编辑源代码]

Lambda表达式可以通过捕获列表访问外部作用域的变量。捕获方式有多种:

捕获方式比较
捕获语法 描述
[ ] 不捕获任何变量
[=] 以值捕获所有变量(隐式值捕获)
[&] 以引用捕获所有变量(隐式引用捕获)
[x] 仅以值捕获x
[&x] 仅以引用捕获x
[=, &x] 默认以值捕获,但x以引用捕获
[&, x] 默认以引用捕获,但x以值捕获

捕获示例[编辑 | 编辑源代码]

#include <iostream>

int main() {
    int x = 10;
    int y = 20;
    
    // 值捕获x,引用捕获y
    auto lambda = [x, &y]() {
        std::cout << "x (值捕获): " << x << ", y (引用捕获): " << y << std::endl;
        y++;  // 可以修改y,因为它是引用捕获
    };
    
    lambda();
    std::cout << "调用后 y 的值: " << y << std::endl;
    
    return 0;
}

输出:

x (值捕获): 10, y (引用捕获): 20
调用后 y 的值: 21

参数与返回类型[编辑 | 编辑源代码]

Lambda表达式的参数列表和返回类型与普通函数类似,但有几点特殊之处:

自动返回类型推导[编辑 | 编辑源代码]

当Lambda体只包含一个return语句时,返回类型可以省略:

auto square = [](int x) { return x * x; };

显式指定返回类型[编辑 | 编辑源代码]

当Lambda体包含多个return语句或复杂逻辑时,应显式指定返回类型:

auto absolute = [](int x) -> int {
    if (x >= 0)
        return x;
    else
        return -x;
};

实际应用案例[编辑 | 编辑源代码]

与STL算法结合[编辑 | 编辑源代码]

Lambda表达式常与STL算法一起使用,使代码更简洁:

#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    std::vector<int> numbers = {1, 2, 3, 4, 5};
    
    // 使用Lambda作为谓词
    auto is_even = [](int n) { return n % 2 == 0; };
    
    // 统计偶数数量
    int count = std::count_if(numbers.begin(), numbers.end(), is_even);
    std::cout << "偶数数量: " << count << std::endl;
    
    // 就地修改vector
    std::for_each(numbers.begin(), numbers.end(), [](int &n) { n *= 2; });
    
    // 输出结果
    for (int n : numbers) {
        std::cout << n << " ";
    }
    std::cout << std::endl;
    
    return 0;
}

输出:

偶数数量: 2
2 4 6 8 10 

作为回调函数[编辑 | 编辑源代码]

Lambda非常适合作为回调函数使用:

#include <iostream>
#include <functional>

void process_data(int x, int y, std::function<void(int)> callback) {
    int result = x + y;
    callback(result);
}

int main() {
    process_data(5, 3, [](int result) {
        std::cout << "处理结果: " << result << std::endl;
    });
    
    return 0;
}

输出:

处理结果: 8

高级特性[编辑 | 编辑源代码]

可变Lambda (mutable)[编辑 | 编辑源代码]

默认情况下,值捕获的变量在Lambda内是const的。使用mutable关键字可以修改这些副本:

#include <iostream>

int main() {
    int x = 0;
    
    auto counter = [x]() mutable {
        x++;  // 修改捕获的副本
        std::cout << "计数: " << x << std::endl;
        return x;
    };
    
    counter();  // 计数: 1
    counter();  // 计数: 2
    std::cout << "原始x: " << x << std::endl;  // 原始x未被修改
    
    return 0;
}

输出:

计数: 1
计数: 2
原始x: 0

泛型Lambda (C++14)[编辑 | 编辑源代码]

虽然这是C++14特性,但值得一提。Lambda可以使用auto参数:

auto multiply = [](auto a, auto b) { return a * b; };

性能考虑[编辑 | 编辑源代码]

Lambda表达式通常会被编译器内联优化,性能与普通函数相当。但需要注意:

  • 捕获大量变量或大对象可能影响性能
  • 引用捕获需要注意生命周期问题
  • 复杂的Lambda可能影响编译器优化

总结[编辑 | 编辑源代码]

Lambda表达式是C++11引入的强大特性,它:

  • 简化了函数对象的创建
  • 使代码更简洁易读
  • 便于与STL算法配合使用
  • 支持灵活的变量捕获方式

掌握Lambda表达式可以显著提高现代C++编程的效率和代码质量。

参见[编辑 | 编辑源代码]