lambda函数表达式写法

本文详细介绍了C++11中的Lambda函数,包括其基本语法、返回类型、捕获规则以及在不同场景下的应用实例。

C++11提供了对匿名函数的支持,称为Lambda函数(也叫Lambda表达式). Lambda表达式具体形式如下:

    [capture](parameters)->return-type{body}

  如果没有参数,空的圆括号()可以省略.返回值也可以省略,如果函数体只由一条return语句组成或返回类型为void的话.形如:

     [capture](parameters){body}

  下面举了几个Lambda函数的例子:      

[](int x, int y) { return x + y; } // 隐式返回类型
[](int& x) { ++x; }   // 没有return语句 -> lambda 函数的返回类型是'void'
[]() { ++global_x; }  // 没有参数,仅访问某个全局变量
[]{ ++global_x; }     // 与上一个相同,省略了()

  可以像下面这样显示指定返回类型:  

[](int x, int y) -> int { int z = x + y; return z; }

在这个例子中创建了一个临时变量z来存储中间值. 和普通函数一样,这个中间值不会保存到下次调用. 什么也不返回的Lambda函数可以省略返回类型, 而不需要使用 -> void 形式.
  Lambda函数可以引用在它之外声明的变量. 这些变量的集合叫做一个闭包. 闭包被定义在Lambda表达式声明中的方括号[]内. 这个机制允许这些变量被按值或按引用捕获.下面这些例子就是:  

[]        //未定义变量.试图在Lambda内使用任何外部变量都是错误的.
[x, &y]   //x 按值捕获, y 按引用捕获.
[&]       //用到的任何外部变量都隐式按引用捕获
[=]       //用到的任何外部变量都隐式按值捕获
[&, x]    //x显式地按值捕获. 其它变量按引用捕获
[=, &z]   //z按引用捕获. 其它变量按值捕获

  接下来的两个例子演示了Lambda表达式的用法.  

复制代码
std::vector<int> some_list;
int total = 0;
for (int i=0;i<5;++i) some_list.push_back(i);
std::for_each(begin(some_list), end(some_list), [&total](int x) 
{
    total += x;
});
复制代码

  此例计算list中所有元素的总和. 变量total被存为lambda函数闭包的一部分. 因为它是栈变量(局部变量)total的引用,所以可以改变它的值.  

复制代码
std::vector<int> some_list;
  int total = 0;
  int value = 5;
  std::for_each(begin(some_list), end(some_list), [&, value, this](int x) 
  {
    total += x * value * this->some_func();
  });
复制代码

  此例中total会存为引用, value则会存一份值拷贝. 对this的捕获比较特殊, 它只能按值捕获. this只有当包含它的最靠近它的函数不是静态成员函数时才能被捕获.对protect和priviate成员来说, 这个lambda函数与创建它的成员函数有相同的访问控制. 如果this被捕获了,不管是显式还隐式的,那么它的类的作用域对Lambda函数就是可见的. 访问this的成员不必使用this->语法,可以直接访问.
  不同编译器的具体实现可以有所不同,但期望的结果是:按引用捕获的任何变量,lambda函数实际存储的应该是这些变量在创建这个lambda函数的函数的栈指针,而不是lambda函数本身栈变量的引用. 不管怎样, 因为大数lambda函数都很小且在局部作用中, 与候选的内联函数很类似, 所以按引用捕获的那些变量不需要额外的存储空间.
  如果一个闭包含有局部变量的引用,在超出创建它的作用域之外的地方被使用的话,这种行为是未定义的!
  lambda函数是一个依赖于实现的函数对象类型,这个类型的名字只有编译器知道. 如果用户想把lambda函数做为一个参数来传递, 那么形参的类型必须是模板类型或者必须能创建一个std::function类似的对象去捕获lambda函数.使用 auto关键字可以帮助存储lambda函数,  

auto my_lambda_func = [&](int x) { /*...*/ };
auto my_onheap_lambda_func = new auto([=](int x) { /*...*/ });

  这里有一个例子, 把匿名函数存储在变量,数组或vector中,并把它们当做命名参数来传递 

复制代码
#include<functional>
#include<vector>
#include<iostream>
double eval(std::function<double(double)> f, double x = 2.0){return f(x);}
int main()
{
     std::function<double(double)> f0    = [](double x){return 1;};
     auto                          f1    = [](double x){return x;};
     decltype(f0)                  fa[3] = {f0,f1,[](double x){return x*x;}};
     std::vector<decltype(f0)>     fv    = {f0,f1};
     fv.push_back                  ([](double x){return x*x;});
     for(int i=0;i<fv.size();i++)  std::cout << fv[i](2.0) << "\n";
     for(int i=0;i<3;i++)          std::cout << fa[i](2.0) << "\n";
     for(auto &f : fv)             std::cout << f(2.0) << "\n";
     for(auto &f : fa)             std::cout << f(2.0) << "\n";
     std::cout << eval(f0) << "\n";
     std::cout << eval(f1) << "\n";
     return 0;
}
复制代码

  一个没有指定任何捕获的lambda函数,可以显式转换成一个具有相同声明形式函数指针.所以,像下面这样做是合法的:
 

auto a_lambda_func = [](int x) { /*...*/ };
void(*func_ptr)(int) = a_lambda_func;
func_ptr(4); //calls the lambda.

### C++中Lambda表达式写法与示例 #### 基本语法 C++中的Lambda表达式遵循以下通用格式: ```cpp [capture](parameters) -> return_type { body } ``` - `[capture]`: 捕获列表,用于指定Lambda表达式能够访问的外部变量及其方式。 - `(parameters)`: 参数列表,类似于普通函数的参数。 - `-> return_type`: 返回值类型(可选),如果不指定,默认由编译器推导。 - `{ body }`: 函数体,包含具体的实现逻辑。 --- #### 示例1:无捕获、无参数的Lambda表达式 以下是一个简单的Lambda表达式,不涉及任何外部变量或参数: ```cpp #include <iostream> int main() { auto helloWorld = []() { std::cout << "Hello, World!" << std::endl; }; helloWorld(); // 输出 Hello, World! } ``` 此示例展示了最基本的Lambda表达式形式[^2]。 --- #### 示例2:带参数的Lambda表达式 通过传入参数,Lambda表达式可以执行特定的操作。例如,计算两个整数的和: ```cpp #include <iostream> int main() { auto add = [](int a, int b) -> int { return a + b; }; // 显式指定了返回类型 int result = add(5, 3); std::cout << "Result: " << result << std::endl; // 输出 Result: 8 } ``` 在此示例中,`add` 是一个接受两个整型参数并返回它们和的Lambda表达式[^2]。 --- #### 示例3:捕获外部变量 Lambda表达式可以通过捕获列表访问外部作用域中的变量。支持按值捕获 (`=`) 或按引用捕获 (`&`)。 ##### 按值捕获 按值捕获会复制外部变量的值到Lambda表达式内部: ```cpp #include <iostream> int main() { int x = 10; auto byValue = [x]() { std::cout << "By Value: " << x << std::endl; }; byValue(); // 输出 By Value: 10 x = 20; // 修改外部变量不会影响Lambda内的值 byValue(); // 输出仍然是 By Value: 10 } ``` ##### 按引用捕获 按引用捕获允许Lambda表达式直接操作外部变量: ```cpp #include <iostream> int main() { int y = 10; auto byRef = [&y]() { std::cout << "By Reference: " << ++y << std::endl; }; byRef(); // 输出 By Reference: 11 (y 被修改) byRef(); // 输出 By Reference: 12 (继续修改 y) } ``` 以上两段代码分别演示了按值和按引用捕获的区别[^3]。 --- #### 示例4:混合捕获 可以同时使用多种捕获方式,具体取决于需求。以下是一个复合捕获的示例: ```cpp #include <iostream> int main() { int a = 10, b = 20; auto mixedCapture = [a, &b]() { // 按值捕获 'a',按引用捕获 'b' std::cout << "a in lambda: " << a << std::endl; // 按值捕获 std::cout << "b in lambda before increment: " << b << std::endl; // 按引用捕获 b += 10; // 修改外部变量 'b' std::cout << "b in lambda after increment: " << b << std::endl; }; mixedCapture(); std::cout << "Final value of b: " << b << std::endl; // 外部变量 'b' 已被修改 } ``` 该示例说明了如何在同一Lambda表达式中组合不同的捕获模式[^1]。 --- #### 示例5:作为回调函数 Lambda表达式常用于替代传统的函数对象,特别是在需要传递小型匿名函数的情况下。例如,对向量进行排序: ```cpp #include <iostream> #include <vector> #include <algorithm> int main() { std::vector<int> nums = {3, 1, 4, 2}; std::sort(nums.begin(), nums.end(), [](int a, int b) { return a > b; }); // 自定义降序排序 for (auto num : nums) { std::cout << num << " "; // 输出 4 3 2 1 } } ``` 这段代码利用Lambda表达式实现了自定义比较规则[^4]。 --- #### 特殊情况:捕获`this` 在类成员函数中,Lambda表达式还可以捕获当前对象的`this`指针,从而访问类的成员变量和方法: ```cpp #include <iostream> #include <string> class Person { private: std::string name; public: explicit Person(const std::string& n) : name(n) {} void greet() const { auto sayHello = [this]() { std::cout << "Hello, my name is " << name << "." << std::endl; }; sayHello(); } }; int main() { Person person("Alice"); person.greet(); // 输出 Hello, my name is Alice. } ``` 此处展示了如何通过捕获`this`来访问类的私有成员[^3]。 --- ### 总结 C++中的Lambda表达式提供了灵活且强大的工具,可用于简化代码结构、增强可读性和功能性。无论是简单的算术运算还是复杂的算法设计,都可以借助Lambda表达式完成。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值