C++ primer 第十章 lambda表达式 笔记(含biggies函数实现)

lambda表达式

一个lambda表达式表示一个可调用代码单元,可以理解为一个未命名的内联函数

[capture list](parameter list) -> return type { function body }

其中,我们可以忽略参数列表和返回类型,但必须包括捕获列表和函数体,
例如:auto f = [ ] { return 42; };

完整的biggies函数实现(含大量注释):

/*从vector<string> words中数出长度大于等于sz的单词,并打印每个单词*/

#include<iostream>
#include<vector>
#include<string>
#include<algorithm>

//是否返回复数形式
std::string make_plural(size_t ctr, const std::string& word, const std::string& ending);	
//字典序,并删除重复单词									
void elimDups(std::vector<std::string>& words);

void biggies(std::vector<std::string>& words,
	std::vector<std::string>::size_type sz) {

	elimDups(words);
	
	//按长度排序,长度相同的单词维持字典序
	stable_sort(words.begin(), words.end(),
		[](const std::string& a, const std::string& b) { return a.size() < b.size(); });
		
	//获取一个迭代器,指向第一个满足size()>=sz的元素
	auto wc = find_if(words.begin(), words.end(),
		[sz](const std::string& a) {		
			return a.size() >= sz;
		});		//捕获列表捕获函数内的局部变量
		
	//计算满足size>=sz的元素数目
	auto count = words.end() - wc;

	//输出多少个
	std::cout << count << " " << make_plural(count, "word", "s")
		<< " of length " << sz << " or longer. " << std::endl;
	//输出每个单词
	for_each(wc, words.end(),
		[](const std::string& s) {std::cout << s << " "; });
	std::cout << std::endl;

}

std::string make_plural(size_t ctr, const std::string& word,	//size_t类型表示任何对象所能达到的最大长度,它是无符号整数,方便系统之间的移植,不同系统的size_t的定义可能不同
									const std::string& ending) {	//size_t在32位系统上定义为 unsigned int,也就是32位无符号整型。在64位系统上定义为 unsigned long ,也就是64位无符号整形。
	return (ctr > 1) ? word + ending : word;
}

void elimDups(std::vector<std::string>& words) {
	//字典序
	sort(words.begin(), words.end());
	//unique重排输入范围,使得每个单词只出现一次,不重复区域排在范围前面,返回指向不重复区域之后一个位置的迭代器
	auto end_unique = unique(words.begin(), words.end());
	//使用向量操作erase删除单词
	words.erase(end_unique, words.end());
}

理解lambda的定义和传递

  • 当定义一个lambda时,编译器生成一个与lambda对应的新的没有命名的类类型

  • 当向函数传递一个lambda时,同时定义了一个新类型和该类型的一个对象:传递的参数就是这个没有命名的对象,这个类包含一个对应捕获的变量的数据成员。

lambda捕获变量的方式

  • 值捕获,[v1],在lambda被创建的时候拷贝该变量;
  • 引用捕获,[&v1],须保证该局部变量在lambda执行时存在
    还要注意所指向的对象从创建lambda到执行是否发生改变
  • 隐式捕获,[&]、[=],根据lambda体内代码确定要捕获的变量,其中的符号告诉编译器采用哪种捕获方式。

一般来说,我们应该尽量减少捕获的数据量,来避免潜在的捕获导致的问题。可能的话,应该避免捕获指针和引用。

  • 另外,如果想要修改捕获的变量,值捕获需要加上mutable,引用捕获依赖于变量本身是否是const类型:auto f = [v1] () mutable { return ++v1; };

lambda的返回类型

  • 必须使用尾置返回来指定返回类型;
//尾置返回类型
auto func() -> int(*)[10];	//在原本的出现返回类型的地方放置auto,返回一个指向含有10个整数数组的指针
  • 如果lambda的函数体只包含单句return语句,可以忽略返回类型,编译器会通过return内容推断返回类型;
  • 如果lambda的函数体包含单句return语句之外的内容,且没有指定返回类型,则返回void。

在这里插入图片描述

  • 6
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值