c++:容器操作和初识lambda表达式

本文介绍了C++中的lambda表达式,包括捕获列表、返回类型、参数列表和函数体。通过示例展示了如何在容器操作中使用lambda,并讲解了lambda的捕获方式,如隐式捕获与显式捕获的规则。还提到了可变lambda和指定返回类型的重要性。

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

  1. lambda表达式
    一个lambda表达式具有如下形式:
    [capture list](parameter list) -> return type [function body]
    capture list(捕获列表):lambda所在函数中定义的局部变量的列表;
    return type:返回类型
    parameter list:参数列表
    function body:函数体
//简例
auto f = [] { return 42 };
cout << f() << endl;//打印42
//如果忽略返回类型,lambda根据函数体中的代码推断出返回类型;
//如果函数体只是一个返回语句,则返回类型从返回的表达式的类型推断而来;
//否则,返回类型为void
  1. 一个容器操作和使用lambda表达式的例子
void elimDups(vector<string>& words)//对vector根据字典序重新排序,并且消除相同元素
{
 sort(words.begin(), words.end());
 auto end_unique = unique(words.begin(), words.end());
 words.erase(end_unique, words.end());
}
bool isShorter(const string &s1, const string &s2)//谓词:用来比较string长度大小
{
 return s1.size() < s2.size();
}
string make_plural(size_t ctr, const string& word, const string& ending)
{
 return (ctr > 1) ? word + ending:word;
}
int main()
{
 vector<string> fox;
 fox.push_back("the");
 fox.push_back("quick");
 fox.push_back("red");
 fox.push_back("fox");
 fox.push_back("jumps");
 fox.push_back("over");
 fox.push_back("the");
 fox.push_back("slow");
 fox.push_back("red");
 fox.push_back("turtle");
 elimDups(fox);//字典序排序
 sort(fox.begin(), fox.end(), isShorter);//size排序
 for (auto iter = fox.begin(); iter != fox.end(); ++iter)
 {
  cout << *iter << endl;
 }
 //auto a = [](const string& a, const string& b) {return a.size() < b.size(); };//等同于isShorter
 stable_sort(fox.begin(), fox.end(), isShorter);//size排序下对各个长度再进行字典序排序,isShorter可替换为a
 for (const auto& s : fox)
  cout << s << endl;
 auto sz = 4;
 auto wc = find_if(fox.begin(), fox.end(), [sz](const string& a) {return a.size() >= sz; });//找到第一个size>=sz的元素,返回该位置的迭代器
 auto count = fox.end() - wc;//返回size>=sz的元素数目
 cout << count << " " << make_plural(count, "word", "s") << " of length " << sz << " or longer " << endl;//输出size>=sz元素个数
 for_each(wc, fox.end(), [](const string& s) {cout << s << " "; });//打印所有size>=sz的string,以空格分隔
 //cout << *fox.end() << endl;
 return 0;
}
  1. lambda捕获和返回
    lambda表达式中捕获列表的内容是在lambda创建时拷贝,而不是调用时拷贝
void fcn1()
{
	size_t v1 = 42;//局部变量
	//将v1拷贝到名为f的可调用对象
	auto f = [v1] { return v1; };
	v1 = 0;
	auto j = f();//j为42;f保存了我们创建它时的拷贝
}
void fcn2()
{
	size_t v1 = 42;//局部变量
	//对象f2包含v1的引用
	auto f2 = [&v1} { return v1; };
	v1 = 0;
	auto j = f2();//j为0;f2保存v1的引用,而非拷贝
}

隐式捕获:为了指示编译器推断捕获列表,应在捕获列表中写一个&或=。&代表引用捕获方式,=代表值捕获方式。

//sz为隐式捕获,值捕获方式
wc = find_if(words.begin(),words.end(),[=](const string &s)
	{ return s.size() >= sz; });
//一部分值捕获,一部分引用捕获
void biggies(vector<string> &words,vector<string>::size_type sz,
	ostream &os = cout,char c = ' '{
	//os隐式捕获,引用捕获方式;c显式捕获,值捕获方式
	for_each(words.begin(),words.end(),[&,c](const string &s)
		{os<<s<<c;};
	//os显式捕获,引用捕获方式;c隐式捕获,值捕获方式
	for_each(words.begin(),words.end(),[=,&os](const string &s)
  {os<<s<<c;};

当我们混合使用隐式捕获和显式捕获时,捕获列表中的第一个元素必须是一个&或=。
当混合使用隐式捕获和显式捕获时,显式捕获的变量必须使用与隐式捕获不同的方式

  1. 可变lambda
    如果我们希望能改变一个被捕获的变量的值,就必须在参数列表首加上关键字mutable
void fcn3()
{
	size_t v1 = 42;//局部变量
	//f可以改变他所捕获的变量的值
	auto f = [v1] () mutable { return ++v1; };
	v1 = 0;
	auto j = f();//j为43
}
void fcn4()
{
	size_t v1 = 42;
	//v1是一个非const变量的引用
	auto f2 = [&v1] { return ++v1; };
	v1 = 0;
	auto j = f2();//j为1
}
  1. 指定lambda返回类型
    默认情况下,如果一个lambda体包含除return之外的任何语句,则编译器假定此lambda返回void。被推断返回void的lambda不能返回值。
//正确例子
transform(vi.begin(),vi.end(),vi.begin(),
	[](int i) { return i<0 ? -i : i; };
//transform接受三个参数,前两个指定接受操作的序列,第三个为目的位置
//错误例子
transform(vi.begin(),vi.end(),vi.begin(),
	[](int i) { if(i<0) return -i;else return i; };
//编译器会推断lambda返回void,但他返回了一个int值

当我们需要为一个lambda定义返回类型时,必须使用尾置返回类型

//正确例子
transform(vi.begin(),vi.end(),vi.begin(),
	[](int i)->int { if(i<0) return -i;else return i; };
【为什么还需要学习C++?】 你是否接触很多语言,但从来没有了解过编程语言的本质?你是否想成为一名资深开发人员,想开发别人做不了的高性能程序?你是否经常想要窥探大型企业级开发工程的思路,但苦于没有基础只能望洋兴叹? 那么C++就是你个人能力提升,职业之路进阶的不二之选。【课程特色】 1.课程共19大章节,239课时内容,涵盖数据结构、函数、类、指针、标准库全部知识体系。2.带你从知识与思想的层面从0构建C++知识框架,分析大型项目实践思路,为你打下坚实的基础。3.李宁老师结合4大国外顶级C++著作的精华为大家推出的《征服C++11》课程。【学完后我将达到什么水平?】 1.对C++的各个知识能够熟练配置、开发、部署;2.吊打一切关于C++的笔试面试题;3.面向物联网的“嵌入式”面向大型化的“分布式”开发,掌握职业钥匙,把握行业先机。【面向人群】 1.希望一站式快速入门的C++初学者; 2.希望快速学习 C++、掌握编程要义、修炼内功的开发者; 3.有志于挑战更高级的开发项目,成为资深开发的工程师。 【课程设计】 本课程包含3大模块基础篇本篇主要讲解c++的基础概念,包含数据类型、运算符等基本语法,数组、指针、字符串等基本词法,循环、函数、类等基本句法等。进阶篇本篇主要讲解编程中常用的一些技能,包含类的高级技术、类的继承、编译链接命名空间等。提升篇:本篇可以帮助学员更加高效的进行c++开发,其中包含类型转换、文件操作、异常处理、代码重用等内容。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值