effective c++ 第六章 lamda表达式

Lambda表达式极大地简化了C++编程,特别是在使用STL算法如find_if、sort时,以及自定义智能指针删除器和多线程编程。Lambda使C++更加易用,通过创建闭包实现函数对象的便捷使用。

lamda表达式-lamda-改变了c++语言游戏。这有点让人吃惊,毕竟它并未给这门语言带来新的令人印象深刻的表现力。lamda可以做的任何事情,你都可以用手多敲一些代码来完成。然而lamda在创建函数对象上的便捷性,一天又一天的对c++编程产生了巨大的影响。没有lamda时,使用c++的_if算法(std::find_if,std::remove_if,std::count_if)会很琐碎。而引入lamda之后,琐碎不复存在了。用户化的比较算法也类似(std::sort,std::lower_bound, std::nth_element)。在stl之外,lamda使得用户可以方便的为std::unique_ptr和std::shared_ptr自定义对象删除器。也使得多线程编程中,对条件变量的判断显得更为直接。除了标准库之外,lamda简化了回调函数,接口适配函数以及一次性的上下文函数调用。lamda使c++成为一门令人愉悦的语言。

   lamda的词义会让你困惑,下面例子帮你简单理一理:

             std::find_if(container.begin(),container.end(), [] (int val){return 0 <val && val < 10;});

闭包是lamda在运行时候创建的对象。根据捕获模式不同,闭包持有捕获数据的拷贝或者引用。

当调用std::findf时候,闭包是传递给函数的第三个参数。

闭包类是闭包实例化的类。每个lamda都促使编译器产生一个闭包类。而lamda的代码,将在其闭包类的成员函数中运行。

lamda创建的闭包,经常被用作函数对象参数。在上面std::find_if中正是如此。

然而闭包本身可以被复制,可能会出现一个闭包类型的多个闭包。下面代码:

{

   int   x; //局部变量

  auto c1 = [x](int y) { return x*y > 55;};  c1是landa产生的闭包的一个拷贝

  auto c2 = c1;          // c2是c1的一个拷贝

  auto c3 = c2;          // c3 是c2的一个拷贝

}

c1,c2,c3都是lamda闭包的拷贝。

非正式的情况,不会区分闭包,闭包类以及landa。但在下面条款中,区分哪些在编译期间存在(lamda和闭包类),以及哪些在运行期间存在(闭包对象),并且弄清楚它们之间的联系是非常重要的。

### C++ 中 Lambda 表达式的使用与语法 #### 什么是 Lambda 表达式? Lambda 表达式是一种匿名函数,在 C++11 标准中被引入。它的主要作用是在需要函数的地方直接编写代码块,而无需显式定义一个完整的函数[^2]。 #### 基本语法 Lambda 表达式的通用形式如下: ```cpp [capture](parameters) -> return_type { body } ``` - **`capture`**: 捕获列表,用于指定外部变量如何被捕获到 Lambda 函数的作用域中。 - `[]`: 不捕获任何外部变量。 - `[&var]`: 按引用方式捕获单个变量 `var`。 - `[=]`: 按值捕获所有外部变量。 - `[this]`: 捕获当前类实例的指针(即 `this`),以便访问成员变量和方法。 - **`parameters`**: 参数列表,类似于普通函数的参数声明。 - **`return_type`**: 返回类型,默认情况下可以省略,编译器会自动推导返回类型。 - **`body`**: 函数体,包含具体的实现逻辑。 #### 示例:基本用法 下面是一个简单的例子,展示如何创建并调用 Lambda 表达式: ```cpp #include <iostream> using namespace std; int main() { auto add = [](int a, int b) -> int { return a + b; }; // 定义一个加法操作的 Lambda cout << "Result of addition: " << add(3, 4) << endl; return 0; } ``` 在这个例子中,我们通过 Lambda 创建了一个名为 `add` 的匿名函数,并将其赋给 `auto` 类型的变量。该 Lambda 接受两个整数作为输入参数,并返回它们的和[^2]。 #### 存储在容器中的 Lambda 表达式 Lambda 表达式不仅可以立即执行,还可以存储起来供后续多次调用。例如,我们可以将多个 Lambda 表达式存入 `std::vector<std::function<int(int)>>` 并逐一调用: ```cpp #include <iostream> #include <vector> #include <functional> // 需要包含 functional 头文件来支持 std::function using namespace std; int main() { vector<function<int(int)>> v; // 存储 Lambda 表达式的向量 v.push_back([](int x) { return x + 1; }); // 加一操作 v.push_back([](int x) { return x * 2; }); // 取双倍操作 for (const auto& f : v) { cout << f(2) << " "; // 调用每个 Lambda 并传参 } return 0; } // 输出结果为:3 4 [^1] ``` #### 结合 STL 算法使用的 Lambda 表达式 Lambda 表达式常用于简化 STL 算法的操作。以下示例展示了如何利用 Lambda 打印数组中的每一个元素: ```cpp #include <iostream> #include <vector> #include <algorithm> // 包含 for_each 和其他算法头文件 using namespace std; int main() { vector<int> vec = {1, 2, 3, 4, 5}; for_each(vec.begin(), vec.end(), [](int x) { cout << x << " "; }); cout << endl; return 0; } // 输出结果为:1 2 3 4 5 [^3] ``` #### 捕获机制详解 捕获列表决定了 Lambda 如何获取其所在范围内的局部变量。以下是几种常见的捕获方式及其行为: - **按值捕获 (`=`)**: 当前范围内所有的变量都会以副本的形式传递给 Lambda。这意味着即使原始变量发生变化,Lambda 内部仍然保留的是最初的值。 ```cpp int value = 10; auto lambda = [=]() mutable { return ++value; }; cout << lambda(); // 输出可能不等于原值,因为这里是拷贝后的修改 ``` - **按引用捕获 (`&`)**: 如果希望 Lambda 修改外部变量,则应采用按引用的方式捕获这些变量。 ```cpp int count = 0; auto increment = [&count]() { count++; }; increment(); cout << count; // 输出为 1 ``` - **混合捕获**: 同时存在按值和按引用两种捕获模式也是可行的。 ```cpp int x = 1, y = 2; auto mixed_lambda = [x, &y]() { return x + y; }; y += 10; cout << mixed_lambda(); // 输出为 1 + (2 + 10),即 13 ``` --- ### 总结 C++ 中的 Lambda 表达式提供了一种简洁的方式来定义小型匿名函数,适用于多种场景,比如事件处理程序、STL 算法以及更复杂的闭包结构。掌握 Lambda 的语法和特性对于提高开发效率至关重要。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值