说明:C++11中的Lambda表达式是一种允许创建匿名函数对象的语法结构。Lambda表达式可以捕获作用域中的变量,并且可以像普通函数一样被调用。它们是C++11标准中引入的一个重要特性,旨在提供一种方便的方式来定义内联的小型函数,特别适用于编写回调函数、线程任务、以及与STL算法结合使用的场景。
Lambda表达式的基本语法如下:
[捕获列表](参数列表) -> 返回类型 {函数体
}
其中概念解读如下:
- 捕获列表:定义了Lambda表达式可以访问的外部变量。可以捕获值、引用或不捕获(默认情况下,Lambda不能访问外部变量)。
- 参数列表:与普通函数的参数列表类似,可以有或没有参数,参数列表也可以省略。
- 返回类型:Lambda表达式的返回类型可以显式指定,也可以由编译器根据函数体自动推导。
- 函数体:包含Lambda表达式的代码实现。
在使用Lambda表达式前我们先了解下为什么引入Lambda表达式。知其然知其所以然。
1 C++11 为什么引入Lambda表达式?
C++11引入Lambda表达式的目的是为了提供一种方便、灵活且表达性强的方式来定义匿名函数。Lambda表达式的引入主要是基于以下几个原因和目标:
- 代码封装和复用:Lambda表达式允许在代码中直接定义函数对象,这有助于封装一小段相关的代码,使得代码更加模块化。这种方式可以减少额外的函数定义,避免全局函数的污染,并且使得相关功能更加紧凑和易于复用。
- 简洁性:在C++11之前,如果需要传递一个函数作为参数或者在循环中使用一个临时的函数对象,程序员通常需要定义一个命名的函数或者使用函数指针。Lambda表达式提供了一种更加简洁的方式来创建这些临时的函数对象,从而简化了代码。
- 捕获上下文:Lambda表达式可以捕获其创建时周围的变量,这使得Lambda表达式可以访问定义它的函数的局部变量。这种特性非常有用,尤其是在需要使用到这些局部变量的回调函数或者模板函数中。
- 支持函数式编程范式:Lambda表达式是函数式编程范式的一个重要组成部分。通过引入Lambda表达式,C++开始支持更多的函数式编程技术,如高阶函数、闭包等,这为程序员提供了更多的编程选择和灵活性。
- 与STL和算法结合:STL(Standard Template Library)是C++的一个重要组成部分,它提供了一系列模板化的容器和算法。Lambda表达式可以非常方便地与STL算法结合使用,作为算法的参数传递,从而实现各种复杂的操作,如过滤、转换、查找等。
- 增强表达力:Lambda表达式增强了C++的表达力,使得一些原本需要复杂模板元编程或宏定义的功能,现在可以用更加直观和易于理解的方式来实现。
- 适应多核和并行计算:随着多核和多线程计算的普及,Lambda表达式提供了一种方便的方式来定义并行任务。结合C++11的线程库和其他并行编程库,Lambda表达式可以轻松地在多线程环境中使用。
- 与现代C++开发相适应:随着C++语言的发展,现代C++开发趋向于更加简洁、模块化和函数式。Lambda表达式的引入是与这一趋势相适应的,它使得C++能够更好地与其他现代编程语言接轨。
综上所述,Lambda表达式的引入是为了提高C++的编程灵活性、代码的可读性和编写效率,同时也使得C++能够更好地适应现代编程的需求和趋势。
2 Lambda表达式使用详解
Lambda表达式是C++11中一个非常强大的特性,它允许你定义一个匿名函数对象,可以在定义它的地方立即使用,或者将其赋给一个变量以便稍后使用。Lambda表达式在STL算法、多线程编程、回调机制等多种场景中都非常有用。以下是一些详细的例子,展示了Lambda表达式在不同情况下的用法:
2.1 简单的Lambda表达式
参考代码如下:
// 定义一个Lambda表达式,接受两个int参数,返回它们的和
auto add = [](int a, int b) { return a + b; };
int result = add(2, 3); // 调用Lambda表达式,result 为 5
2.2 使用Lambda表达式与STL算法
参考代码如下:
#include <vector>
#include <algorithm>std::vector<int> numbers = {1, 2, 3, 4, 5};
// 使用Lambda表达式作为std::for_each的第一个参数
std::for_each(numbers.begin(), numbers.end(), [](int num) {std::cout << num << std::endl; // 打印每个数字
});
// 使用Lambda表达式进行排序,根据数字的奇偶性
std::sort(numbers.begin(), numbers.end(), [](int a, int b) {return a % 2 == 0 && b % 2 != 0;
});
2.3 捕获上下文变量
参考代码如下:
// 定义一些局部变量
int x = 10;
int y = 20;
// 定义一个Lambda表达式,捕获x和y
auto lambda = [&x, &y]() { return x + y; };
int result = lambda(); // 调用Lambda表达式,result 为 30
2.4 在多线程编程中使用Lambda表达式
参考代码如下:
#include <iostream>
#include <thread>void print(int n) {std::cout << "Hello from thread " << n << std::endl;
}int main() {std::thread t(print, 1); // 使用Lambda表达式启动线程t.join(); // 等待线程结束return 0;
}
2.5 Lambda表达式作为函数参数
参考代码如下:
// 定义一个接受Lambda表达式作为参数的函数。
void executeLambda(std::function<void()> lambda) {lambda(); // 调用传入的Lambda表达式
}int main() {executeLambda([]() {std::cout << "Lambda is called" << std::endl;});return 0;
}
2.6 使用Lambda表达式进行类型推导
参考代码如下:
// 使用auto推导Lambda表达式的类型。
auto square = [](int x) -> int {return x * x;
};
int squared = square(5); // squared 为 25
2.7 Lambda表达式与模板函数结合
参考代码如下:
template <typename Func>
void runFunc(Func f) {f();
}int main() {runFunc([]() {std::cout << "Hello from a template function!" << std::endl;});return 0;
}
2.8 Lambda表达式捕获所有局部变量
参考代码如下:
// 定义一些局部变量
int a = 5;
int b = 10;
// 定义一个Lambda表达式,捕获所有局部变量
auto lambda = [a, b]() {std::cout << "a = " << a << ", b = " << b << std::endl;
};
lambda(); // 输出:a = 5, b = 10
通过这些例子,我们可以看到Lambda表达式在C++11中的多样性和实用性。它不仅可以简化代码,还可以提高代码的可读性和可维护性。Lambda表达式的引入为C++编程带来了更多的灵活性和便利。