C++11 lambda表达式

本文深入探讨了C++11引入的lambda表达式,详细解释了其概念、使用方法以及与其他类似功能的区别。通过具体实例展示了如何在实际编程中灵活运用lambda表达式,包括创建无参数或无返回值的lambda表达式,向其传递参数,并利用捕获列表访问外部作用域中的变量。此外,还介绍了lambda表达式如何在排序算法中实现自定义排序规则。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

lambda表达式是C++11新特征中的一部分。lambda和仿函数有些许相同的地方,仿函数在之前的博文中已经具体的提及到了。

1、函数调用运算符(仿函数)

仿函数的实质就是在类中重载了()运算符,使得对象调用()的形式与函数的调用形式基本一致。仿函数在之前的博客中已经有详细的解释,具体可查阅之前的博客。

2、lambda表达式

一个lambda表达式表示一个可以调用的单元。我们可以将它理解成一个未命名的内联函数。和函数相似的是lambda具有一个返回类型、一个参数列表和一个函数体。
lambda表达式的形式可以抽象表示为:
[capture list] (parameter list) -> return type {function body}
capture list:捕获列表,lambda表达式中局部变量定义的列表。捕获列表不能省略,但是里面可以不定义内容直接写成[]形式。

              
parameter list:参数列表,这个和普通函数没有什么区别,值得注意的是,lambda表达的参数列表中不支持默认参数!                        参数列表在lambda表达式中是可以省略的部分。
return type:    返回值类型,和普通函数一样。返回值类型在lambda表达式中是可以省略的部分。
function body:  函数体,和普通函数一样。不可省略。
lambda表达式必须使用尾置返回来指定返回类型。


(1)忽略参数列表和返回类型的lambda表达式

auto f = [] {return 42};


上述,定义了一个可调对象f,他不接受参数,返回42。
lambda表达式的调用方式也与普通函数的调用方式相同,都是使用调用运算符。


cout<< f() << endl;


完整例子如下:


#include <iostream>
using namespace std;

int main()
{
	auto f = []{ return 42; };
	cout << f() << endl;
	return 0;
}

(2)向lambda 传递参数


首先看一个例子。现在要求我们将一个vector容器中的string数据按照string的长短进行排序。根据STL中algorithm,有sort函数可以使用。sort函数在cpp标准中的定义如下:
a> template <class RandomAccessIterator>
   void sort (RandomAccessIterator first, RandomAccessIterator last);
b> template <class RandomAccessIterator, class Compare>
   void sort (RandomAccessIterator first, RandomAccessIterator last, Compare comp);

其中b版本可以带入一个我们自己定义的排序规则函数。按照分析可以写出如下的代码:

bool isShorter(const string &s1, const string &s2)
{
	return s1.size() < s2.size();
}
//按照排序规则对words序列中的元素进行排序
sort(words.begin(), words.end(), isShorter)


使用lambda完成一个和isShorter函数一样功能的表达式:
auto f = [](const string& s1, const string& s2){return s1.size() < s2.size();};

(3)使用捕获列表


一个lambda表达式通过将局部变量包含在其捕获列表中来指出将会使用这些变量。捕获列表指引lambda在其内部访问局部变量所需的信息。

void biggies(vector<string> &words, vector<string>::size_type sz)
{
	elimDups(words);			//将words按照字典序排序,删除重复单词
	//按照长度排序,长度相同的单词维持字典顺序
	stable_sort(words.begin(),words.end(),
	            [](const string& s1, const string& s2){return s1.size() < s2.size();});	
	
	auto wc = find_if(words.begin(),words.end(),
					  [sz](const string &a)
					       {return a.size() >= sz;};
}

3、lambda捕获和返回


当定义一个lambda的时候,编译器生成一个与lambda对应的新的(未命名的)类类型。当传递一个lambda时,同时定义了一个新类型和该类型的对象:传递的参数就是此编译器生成的类类型的未命名的对象。类似的,当使用auto定义一个用lambda初始化的变量时,定义一个从lambda生成的类型的对象。






### C++11 Lambda表达式使用教程 #### 定义与基本语法 C++11引入了lambda表达式这一强大特性,使得开发者能够更加便捷地定义和创建匿名函数。这种新的功能不仅简化了代码编写过程,还提升了程序的功能性和执行效率[^1]。 Lambda表达式的通用形式如下: ```cpp [capture](parameters)->return_type { body } ``` 其中`capture`表示捕获列表,用于指定如何访问外部作用域中的变量;`parameters`代表参数列表;`->return_type`可选部分用来显式声明返回类型;最后是函数体`body`[^2]。 #### 捕获列表详解 捕获列表允许lambda表达式获取其所在环境内的局部变量或全局变量。常见的几种方式包括但不限于按值传递(`[var]`)、按引用传递(` [&var] `),以及默认全部按值/引用捕获(` [= ] / [&] `)[^3]。 ##### 示例:按值捕获 当采用按值的方式捕获时,意味着会复制一份原始数据供内部逻辑操作而不影响原值。 ```cpp #include <iostream> using namespace std; int main(){ int value = 42; auto func_by_value = [value]() { cout << "Value captured by copy: " << value << endl; }; ++value; // 修改外界的value func_by_value(); // 输出的是未修改前的数值 } ``` ##### 示例:按引用捕获 相反地,如果选择了按引用的形式,则任何对于被捕获变量的操作都会直接影响到实际存在的那个实例。 ```cpp #include <iostream> using namespace std; int main(){ int ref_val = 88; auto modify_ref = [&ref_val]() mutable{ ++ref_val; cout << "Modified reference-captured variable to : " << ref_val << endl; }; modify_ref(); } ``` #### 实际应用场景举例 考虑这样一个场景——我们需要交换两个整型数的位置而无需借助额外的空间开销。此时可以巧妙运用带有适当捕获机制的lambda表达式来完成任务[^5]。 ```cpp void swapTwoNumbers(int &num1, int &num2){ auto swapper = [&](int &a, int &b){ int temp=a;a=b;b=temp; }; swapper(num1,num2); } // 或者更为简洁的做法直接在lambda体内处理 auto direct_swap=[&](int &x,int &y){swap(x,y);} direct_swap(a,b); ``` #### 关于赋值行为的重要注意事项 值得注意的一点在于,尽管可以通过拷贝构造的方式来生成另一个具有相同行为的新对象,但是不同lambda表达式之间不允许互相赋值,即便它们看起来拥有完全一致的结构和语义[^4]。 ```cpp auto hello_world_1=[](){std::cout<<"Hello World"<<std::endl;}; auto hello_world_2=[](){std::cout<<"Hello World"<<std::endl;}; // 下面这行会导致编译错误 //hello_world_1=hello_world_2; ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

空空的司马

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值