C++详细分析lambda表达式的本质

 更新时间:2022年06月24日 10:55:15   作者:配的上了吗  
Lambda表达式是现代C++在C ++ 11和更高版本中的一个新的语法糖 ,在C++11、C++14、C++17和C++20中Lambda表达的内容还在不断更新。 lambda表达式(也称为lambda函数)是在调用或作为函数参数传递的位置处定义匿名函数对象的便捷方法

例:

stable_sort(words.begin(), words.end(), 
		[](const string& s1, const string& s2) 
		{ return s1.size() < s2.size(); });
class ShorterString 
{
public:
	bool operator()(const string& s1,const string& s2)const
	{
		return s1.size() < s2.size();
	}
};
// 等价于
stable_sort(words.begin(), words.end(), ShorterString();
// 或者
ShorterString s;
stable_sort(words.begin(), words.end(), s;

写一个lambda表达式之后,编译器将该表达式翻译为一个未命名类的未命名对象。

且lambda表达式产生的类中含有一个重载的函数调用运算符。且该函数调用运算符成员的形参列表和函数体与lambda表达式完全一样。

此时,stable_sort的内部代码每次比较两个string时就会"调用"这一对象。此对象将会调用运算符的函数体,返回true or false

我们知道,lambda表达式可以捕获变量,且分为引用捕获和值捕获,而当引用捕获时,由程序负责确保lambda执行时引用所引的对象确实存在,而编译器就会直接使用该引用,无需在lambda产生的类中将其存储为数据成员

根据上一段话的介绍,大致也可以猜想出,若采用值捕获的方式,被值捕获的变量会被拷贝至lambda中。因此,这种lambda产生的类必须为每个值捕获的变量创建对应的数据成员。 同时创建构造函数。令其使用捕获的变量的值来初始化数据成员。

默认情况下lambda表达式不可以改变它捕获的变量。所以重载函数调用运算符的函数默认情况下会被定义为const。

举例:

auto wc = find_if(words.begin(), words.end(), 
    [sz] (const string& s) { return s.size() >= sz; } );
class Sizecomp
{
public:
	Sizecomp(size_t n) :sz(n) {}
	bool operator()(const string& s)const
	{
		return s.size() >= sz;
	}
private:
	size_t sz;
};
// 等价于
auto wc = find_if(words.begin(), words.end(), Sizecomp(sz));

此类无默认构造函数,因此要想使用这个类必须提供一个实参。数据成员sz对应通过值捕获的变量。用此值捕获变量的值来初始化该sz数据成员。

在C++11中, lambda是通过匿名的函数对象来实现的,因此我们可以把lambda看作是对函数对象在使用方式上进行的简化。

当代码需要一个简单的函数,并且这个函数并不会在其他地方被使用时,就可以使用lambda来实现,此时它所起的作用类似于匿名函数。 但如果这个函数需要多次使用,并且它需要保存某些状态的话,使用函数对象则更合适一些。

练习:编写程序,统计一个vector<string>中元素size处于1-9的有几个,大于等于10的有几个

class StrLenBetween
{
public:
	StrLenBetween(int m, int x) :min(m), max(x) {}
	bool operator()(const string& s)const
	{
		return s.size() >= min && s.size() <= max;
	}
private:
	int min;
	int max;
};
void readStr(istream& is, vector<string>& v)
{
	string s;
	while (is >> s)
		v.push_back(s);
}
int main()
{
	vector<string> vec;
	readStr(cin, vec);
	const int min = 1;
	const int max = 10;
	cout << "len 1~9 : " << count_if(vec.begin(), vec.end(), [min, max](const string& s)->bool {return s.size() >= 1 && s.size() <= 9; }) << endl;
	cout << "len >= 10 : " << count_if(vec.begin(), vec.end(), [max](const string& s)->bool {return s.size() >= max; }) << endl;
	cout << "len 1~9 : " << count_if(vec.begin(), vec.end(), StrLenBetween(min, max)) << endl;
	return 0;
}

主函数第一个cout和第三个cout意义相同。

到此这篇关于C++详细分析lambda表达式的本质的文章就介绍到这了,更多相关C++lambda表达式内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 详解C++ STL模拟实现list

    详解C++ STL模拟实现list

    这篇文章主要为大家详细介绍了C++如何模拟实现STL容器list,文中的示例代码讲解详细,对我们学习C++有一定帮助,需要的可以参考一下
    2023-01-01
  • C++如何获取鼠标点击位置

    C++如何获取鼠标点击位置

    这篇文章主要介绍了C++如何获取鼠标点击位置问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-08-08
  • C语言实现最大间隙问题实例

    C语言实现最大间隙问题实例

    这篇文章主要介绍了C语言实现最大间隙问题的方法,是一个比较经典的算法设计问题,对于学习算法设计有一定的借鉴价值,需要的朋友可以参考下
    2014-09-09
  • 详谈signed 关键字

    详谈signed 关键字

    c++中关键字有几十个,其中类型修饰关键字有long, short, singed, unsigned。今天我们就来谈一下经常被大家忽视的signed关键字
    2015-01-01
  • C++异常处理的方式总结

    C++异常处理的方式总结

    C++有一套独立的异常处理机制,相信大家一定听说过try,catch这两
    个词,今天就来做详细的介绍,文中通过代码示例给大家介绍的非常详细,具有一定参考价值,需要的朋友可以参考下
    2023-12-12
  • 从汇编看c++中引用与指针的使用分析

    从汇编看c++中引用与指针的使用分析

    在c++中,引用和指针具有相同的作用,都可以用来在函数里面给变函数外面对象或者变量的值,下面就来看他们的原理
    2013-05-05
  • Qt数据库应用之超级自定义委托

    Qt数据库应用之超级自定义委托

    Qt中需要用到自定义委托的情形很多,比如提供下拉框选择,进度条展示下载进度啥的,默认的单元格是没有这些效果的,需要自己单独用委托的形式来展示。本文将为大家介绍Qt中如何进行超级自定义委托,需要的可以参考一下
    2022-03-03
  • C++开发在IOS环境下运行的LRUCache缓存功能

    C++开发在IOS环境下运行的LRUCache缓存功能

    本文着重介绍如何在XCODE中,通过C++开发在IOS环境下运行的缓存功能。算法基于LRU,最近最少使用,需要的朋友可以参考下
    2012-11-11
  • C++ OpenCV实战之标记点检测的实现

    C++ OpenCV实战之标记点检测的实现

    这篇文章主要介绍了如何利用C++ OpenCV实现关键点的检测,文中的示例代码讲解详细,对我们学习OpenCV有一定帮助,感兴趣的小伙伴可以了解一下
    2022-03-03
  • 基于Matlab制作一个数独求解器

    基于Matlab制作一个数独求解器

    这篇文章主要为大家详细介绍了如何利用Matlab制作一个数独求解器,文中的示例代码讲解详细,对我们学习Matlab有一定帮助,需要的可以参考一下
    2022-05-05

最新评论