Linux
Linux software install
Google repo的使用
Vector AP StartApplication编译脚本解析
Yocto的cmake版本升级
不能自动安装的解决方式
S32G-BSP35.0-SDK使用方法
S32G从SDK生成文件系统的制作过程
Linux Samba设置
Linux添加双网卡
S32G USB-Redirector安装指南
VS code自动生成Doxygen格式注释
Linux下使用多线程下载
使用pandoc 生成带中文的pdf
minicom无法输入的问题解决办法
使用 systemd unit 添加一条路由规则
CMake 教程
步骤 1:基本起点
步骤 2:添加lib库
步骤 3:为库添加使用要求
步骤 4:添加生成器表达式
步骤 5:安装和测试
步骤 6:添加支持测试仪表板
步骤 7: 添加系统内省
步骤 8:自定义命令和生成的文
步骤 9:打包安装程序
步骤 10:选择静态库或共享库
步骤 11:添加导出配置
步骤 12:打包 Debug 和 Release
添加虚拟网卡
Vector AP 去掉防篡改校验
Vector AP startapplication编译与使用
Vector AP问题汇总
Vector AP大型项目开发流程
Vector AP EM
Vector AP 最简单的开发示例
Linux kernel 版本降级
Vector AP StartApplicaiton
startappplication-machine-design
startapplicaiton-machine-integration
amsr-vector-fs-em-executionmanager-design
amsr-vector-fs-em-executionmanager
Vector AP 复杂模型的开发
第一章 Machine和MachineDesign
第二章 Execute Manager
第三章 Log
第四章 State Manager
第五章 State Manager 源码的理解
第六章 Someip daemon
第七章 IPC Service Discovery Daemon
crond的使用方法
解决蓝牙鼠标在 Ubuntu 中单位时间内断开的问题
VPS服务器自建教程
v2rayA的客户端使用配置
GDB调试指南入门篇:揭开程序运行世界的神秘面纱
GDB调试指南高级篇:成为调试专家,掌控程序的命运
Linux安装PyQt5并配置Qt Designer
ADB 命令大全
GoogleTest(一)
GoogleTest(二)简单的TEST宏
GoogleTest(三)简单类函数测试
C++ Template
1. 函数模板
2. 类模板
3. 非类型模板参数
软件版本号规范
EPOLL
C++手札
C++ 使用{}初始化有哪些好处?
现代 C++ decltype 深入解析
函数对象(functor)
Linux性能剖析:CPU、内存、网络与I/O压力测试
AP StateManager
C++ Lambda表达式
C++ 中的Lambda表达式
Lambda 表达式语法
Lambda 表达式的示例
手动发送UDP数据包
pyqt5生成的UI界面不能输入中文
自己搭建repo镜像
摄影
Sony仿富士PP值设置
诗词歌赋
本文档使用 MrDoc 发布
-
+
首页
Lambda 表达式的示例
## 本文内容 1. [声明 Lambda 表达式](#declaringLambdaExpressions) 2. [调用 Lambda 表达式](#callingLambdaExpressions) 3. [嵌套 Lambda 表达式](#nestingLambdaExpressions) 4. [高阶 Lambda 函数](#higherOrderLambdaExpressions) 5. [在函数中使用 Lambda 表达式](#methodLambdaExpressions) 6. [配合使用 Lambda 表达式和模板](#templateLambdaExpressions) 7. [处理异常](#ehLambdaExpressions) 8. [配合使用 Lambda 表达式和托管类型 (C++/CLI)](#managedLambdaExpressions) 本文演示如何在你的程序中使用 lambda 表达式。 ## 声明 Lambda 表达式 ### 示例 1 由于 lambda 表达式已类型化,所以你可以将其指派给 **`auto`** 变量或 [`function`](https://learn.microsoft.com/zh-cn/cpp/standard-library/function-class?view=msvc-170) 对象,如下所示: ```cpp // declaring_lambda_expressions1.cpp // compile with: /EHsc /W4 #include <functional> #include <iostream> int main() { using namespace std; // Assign the lambda expression that adds two numbers to an auto variable. auto f1 = [](int x, int y) { return x + y; }; cout << f1(2, 3) << endl; // Assign the same lambda expression to a function object. function<int(int, int)> f2 = [](int x, int y) { return x + y; }; cout << f2(3, 4) << endl; } ``` 此示例产生以下输出: Output ```shell 5 7 ``` ### 备注 有关详细信息,请参阅 [`auto`](https://learn.microsoft.com/zh-cn/cpp/cpp/auto-cpp?view=msvc-170)、[`function` 类](https://learn.microsoft.com/zh-cn/cpp/standard-library/function-class?view=msvc-170)和[函数调用](https://learn.microsoft.com/zh-cn/cpp/cpp/function-call-cpp?view=msvc-170)。 虽然 lambda 表达式多在函数的主体中声明,但是可以在初始化变量的任何地方声明。 ### 示例 2 Microsoft C++ 编译器将在声明而非调用 lambda 表达式时,将表达式绑定到捕获的变量。 以下示例显示一个通过值捕获局部变量 `i` 并通过引用捕获局部变量 `j` 的 lambda 表达式。 由于 lambda 表达式通过值捕获 `i`,因此在程序后面部分中重新指派 `i` 不影响该表达式的结果。 但是,由于 lambda 表达式通过引用捕获 `j`,因此重新指派 `j` 会影响该表达式的结果。 C++ 复制 ```cpp // declaring_lambda_expressions2.cpp // compile with: /EHsc /W4 #include <functional> #include <iostream> int main() { using namespace std; int i = 3; int j = 5; // The following lambda expression captures i by value and // j by reference. function<int (void)> f = [i, &j] { return i + j; }; // Change the values of i and j. i = 22; j = 44; // Call f and print its result. cout << f() << endl; } ``` 此示例产生以下输出: Output ```auto 47 ``` ## 调用 Lambda 表达式 你可以立即调用 Lambda 表达式,如下面的代码片段所示。 第二个代码片段演示如何将 lambda 作为自变量传递给标准库算法,例如 `find_if`。 ### 示例 1 以下示例声明的 lambda 表达式将返回两个整数的总和并使用自变量 `5` 和 `4` 立即调用该表达式: ```cpp // calling_lambda_expressions1.cpp // compile with: /EHsc #include <iostream> int main() { using namespace std; int n = [] (int x, int y) { return x + y; }(5, 4); cout << n << endl; } ``` 此示例产生以下输出: ```shell 9 ``` ### 示例 2 以下示例将 Lambda 表达式作为自变量传递给 `find_if` 函数。 如果 lambda 表达式的参数是偶数,则返回 `true`。 ```cpp // calling_lambda_expressions2.cpp // compile with: /EHsc /W4 #include <list> #include <algorithm> #include <iostream> int main() { using namespace std; // Create a list of integers with a few initial elements. list<int> numbers; numbers.push_back(13); numbers.push_back(17); numbers.push_back(42); numbers.push_back(46); numbers.push_back(99); // Use the find_if function and a lambda expression to find the // first even number in the list. const list<int>::const_iterator result = find_if(numbers.begin(), numbers.end(),[](int n) { return (n % 2) == 0; }); // Print the result. if (result != numbers.end()) { cout << "The first even number in the list is " << *result << "." << endl; } else { cout << "The list contains no even numbers." << endl; } } ``` 此示例产生以下输出: ```shell The first even number in the list is 42. ``` ### 备注 有关 `find_if` 函数的详细信息,请参阅 [`find_if`](https://learn.microsoft.com/zh-cn/cpp/standard-library/algorithm-functions?view=msvc-170#find_if)。 有关执行公共算法的 C++ 标准库函数的详细信息,请参阅 [`<algorithm>`](https://learn.microsoft.com/zh-cn/cpp/standard-library/algorithm?view=msvc-170)。 ## 嵌套 Lambda 表达式 ### 示例 你可以将 lambda 表达式嵌套在另一个中,如下例所示。 内部 lambda 表达式将其自变量与 2 相乘并返回结果。 外部 lambda 表达式通过其自变量调用内部 lambda 表达式并在结果上加 3。 ```cpp // nesting_lambda_expressions.cpp // compile with: /EHsc /W4 #include <iostream> int main() { using namespace std; // The following lambda expression contains a nested lambda // expression. int timestwoplusthree = [](int x) { return [](int y) { return y * 2; }(x) + 3; }(5); // Print the result. cout << timestwoplusthree << endl; } ``` 此示例产生以下输出: Output 复制 ```shell 13 ``` ### 备注 在该示例中,`[](int y) { return y * 2; }` 是嵌套的 lambda 表达式。 ## 高阶 Lambda 函数 ### 示例 许多编程语言支持“高阶函数”的概念。高阶函数是一个 lambda 表达式,它采用另一个 lambda 表达式作为其自变量,或返回 lambda 表达式。 你可以使用 [`function`](https://learn.microsoft.com/zh-cn/cpp/standard-library/function-class?view=msvc-170) 类,使得 C++ lambda 表达式具有类似高阶函数的行为。 以下示例显示返回 `function` 对象的 lambda 表达式和采用 `function` 对象作为其参数的 lambda 表达式。 ```cpp // higher_order_lambda_expression.cpp // compile with: /EHsc /W4 #include <iostream> #include <functional> int main() { using namespace std; // The following code declares a lambda expression that returns // another lambda expression that adds two numbers. // The returned lambda expression captures parameter x by value. auto addtwointegers = [](int x) -> function<int(int)> { return [=](int y) { return x + y; }; }; // The following code declares a lambda expression that takes another // lambda expression as its argument. // The lambda expression applies the argument z to the function f // and multiplies by 2. auto higherorder = [](const function<int(int)>& f, int z) { return f(z) * 2; }; // Call the lambda expression that is bound to higherorder. auto answer = higherorder(addtwointegers(7), 8); // Print the result, which is (7+8)*2. cout << answer << endl; } ``` 此示例产生以下输出: ```cpp 30 ``` ## 在函数中使用 Lambda 表达式 ### 示例 你可以在函数的主体中使用 lambda 表达式。 lambda 表达式可以访问该封闭函数可访问的任何函数或数据成员。 你可以显式或隐式捕获 **`this`** 指针,以提供对封闭类的函数和数据成员的访问路径。 Visual Studio 2017 版本 15.3 或更新版本([`/std:c++17`](https://learn.microsoft.com/zh-cn/cpp/build/reference/std-specify-language-standard-version?view=msvc-170) 及更新版本可用):在原始对象超出范围后,当可能会执行代码的异步或并行操作将使用 lambda 时,按值捕获 **`this`** (`[*this]`)。 可以在函数中显式使用 **`this`** 指针,如下所示: ```cpp // capture "this" by reference void ApplyScale(const vector<int>& v) const { for_each(v.begin(), v.end(), [this](int n) { cout << n * _scale << endl; }); } // capture "this" by value (Visual Studio 2017 version 15.3 and later) void ApplyScale2(const vector<int>& v) const { for_each(v.begin(), v.end(), [*this](int n) { cout << n * _scale << endl; }); } ``` 你也可以隐式捕获 **`this`** 指针: ```cpp void ApplyScale(const vector<int>& v) const { for_each(v.begin(), v.end(), [=](int n) { cout << n * _scale << endl; }); } ``` 以下示例显示封装小数位数值的 `Scale` 类。 ```cpp // function_lambda_expression.cpp // compile with: /EHsc /W4 #include <algorithm> #include <iostream> #include <vector> using namespace std; class Scale { public: // The constructor. explicit Scale(int scale) : _scale(scale) {} // Prints the product of each element in a vector object // and the scale value to the console. void ApplyScale(const vector<int>& v) const { for_each(v.begin(), v.end(), [=](int n) { cout << n * _scale << endl; }); } private: int _scale; }; int main() { vector<int> values; values.push_back(1); values.push_back(2); values.push_back(3); values.push_back(4); // Create a Scale object that scales elements by 3 and apply // it to the vector object. doesn't modify the vector. Scale s(3); s.ApplyScale(values); } ``` 此示例产生以下输出: ```shell 3 6 9 12 ``` ### 注解 `ApplyScale` 函数使用 lambda 表达式打印小数位数值与 `vector` 对象中的每个元素的乘积。 lambda 表达式隐式捕获 **`this`** 指针,以便访问 `_scale` 成员。 ## 配合使用 Lambda 表达式和模板 ### 示例 由于 lambda 表达式已类型化,因此你可以将其与 C++ 模板一起使用。 下面的示例显示 `negate_all` 和 `print_all` 函数。 `negate_all` 函数将一元 **`operator-`** 应用于 `vector` 对象中的每个元素。 `print_all` 函数将 `vector` 对象中的每个元素打印到控制台。 ```cpp // template_lambda_expression.cpp // compile with: /EHsc #include <vector> #include <algorithm> #include <iostream> using namespace std; // Negates each element in the vector object. Assumes signed data type. template <typename T> void negate_all(vector<T>& v) { for_each(v.begin(), v.end(), [](T& n) { n = -n; }); } // Prints to the console each element in the vector object. template <typename T> void print_all(const vector<T>& v) { for_each(v.begin(), v.end(), [](const T& n) { cout << n << endl; }); } int main() { // Create a vector of signed integers with a few elements. vector<int> v; v.push_back(34); v.push_back(-43); v.push_back(56); print_all(v); negate_all(v); cout << "After negate_all():" << endl; print_all(v); } ``` 此示例产生以下输出: ```shell 34 -43 56 After negate_all(): -34 43 -56 ``` [](#remarks-4) ## 处理异常 ### 示例 lambda 表达式的主体遵循结构化异常处理 (SEH) 和 C++ 异常处理的原则。 你可以在 lambda 表达式主体中处理引发的异常或将异常处理推迟至封闭范围。 以下示例使用 **`for_each`** 函数和 lambda 表达式将一个 `vector` 对象的值填充到另一个中。 它使用 **`try`**/**`catch`** 块处理对第一个矢量的无效访问。 ```cpp // eh_lambda_expression.cpp // compile with: /EHsc /W4 #include <vector> #include <algorithm> #include <iostream> using namespace std; int main() { // Create a vector that contains 3 elements. vector<int> elements(3); // Create another vector that contains index values. vector<int> indices(3); indices[0] = 0; indices[-1] = 1; // This is not a valid subscript. It will trigger an exception. indices[2] = 2; // Use the values from the vector of index values to // fill the elements vector. This example uses a // try/catch block to handle invalid access to the // elements vector. try { for_each(indices.begin(), indices.end(), [&](int index) { elements.at(index) = index; }); } catch (const out_of_range& e) { cerr << "Caught '" << e.what() << "'." << endl; }; } ``` 此示例产生以下输出: ```shell Caught 'invalid vector<T> subscript'. ``` ### 备注 有关异常处理的详细信息,请参阅[异常处理](https://learn.microsoft.com/zh-cn/cpp/cpp/exception-handling-in-visual-cpp?view=msvc-170)。 ## 配合使用 Lambda 表达式和托管类型 (C++/CLI) ### 示例 lambda 表达式的捕获子句不能包含具有托管类型的变量。 但是,你可以将具有托管类型的实际参数传递到 lambda 表达式的形式参数列表。 以下示例包含一个 lambda 表达式,它通过值捕获局部非托管变量 `ch`,并采用 [System.String](/zh-cn/dotnet/api/system.string) 对象作为其参数。 ```cpp // managed_lambda_expression.cpp // compile with: /clr using namespace System; int main() { char ch = '!'; // a local unmanaged variable // The following lambda expression captures local variables // by value and takes a managed String object as its parameter. [=](String ^s) { Console::WriteLine(s + Convert::ToChar(ch)); }("Hello"); } ``` 此示例产生以下输出: ```shell Hello! ``` ### 备注 你还可以配合使用 lambda 表达式和 STL/CLR 库。 有关详细信息,请参阅 [STL/CLR 库参考](https://learn.microsoft.com/zh-cn/cpp/dotnet/stl-clr-library-reference?view=msvc-170)。 重要 以下公共语言运行时 (CLR) 托管实体中不支持 Lambda:**`ref class`**、**`ref struct`**、**`value class`** 以及 **`value struct`**。
admin
2024年8月28日 14:52
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
Markdown文件
分享
链接
类型
密码
更新密码