9-9 lambda表达式捕获模式的陷阱分析和展示(未归类知识点)

035lambda常见陷阱_捕获列表中的引用_局部变量超出作用域

#include<iostream>
#include<iostream>
#include<cstdlib>
#include<functional>
#include <vector>
#include <algorithm>
#include <ctime>
using namespace std;

//全局变量,每个元素都是function,每个元素都是参数是int,返回值是bool类型
std::vector<std::function<bool(int)>> gv;

void myFunction()
{
	srand((unsigned)time(nullptr));
	int temValue = rand() % 6;//产生一个0-5之间的种子
	gv.push_back(
		[&](int tv)//这里改为按值捕获可以解决=
	{
		if (tv%temValue == 0)//如果tv是temValue的倍数
		{
			return true;

		}
		return false;
	}
	);//把lambda表达式插入vector容器中
}

int main(void)
{
	myFunction();
	cout << gv[0](10) << endl;
	/*
	 * gv[0](10)调用的时候,temValue是个局部变量已经超出作用域了,这里调用有问题
	 * temValue的内存空间已经释放了。解决办法,改为按值捕获。
	 */
	
	system("pause");
	return 0;
}
/*
* (1)lambda常见陷阱_捕获列表中的&_局部变量超出作用域
* 捕获外部区域中的所有变量,并作为引用在lambda表达式中使用。
* 按照引用这种捕获方式,会导致lambda包含绑定到局部变量中的引用。
* (2)
* (3)
* (4)
* (5)
* (6)(7)
*/

036lambda常见陷阱_类中成员变量捕获问题_实际上是捕获的this指针

#include<iostream>
#include<iostream>
#include<cstdlib>
#include<functional>
#include <vector>
#include <algorithm>
#include <ctime>
using namespace std;

//全局变量,每个元素都是function,每个元素都是参数是int,返回值是bool类型
std::vector<std::function<bool(int)>> gv02;



class AT
{
public:
	int m_temvalue = 7;
	void addItem()
	{
		auto temvalue02 = this->m_temvalue;//成员变量转局部变量,lambda表达式捕获
		gv02.push_back(// c++4中允许在lambda表达式形参列表中使用auto
			//[=](auto tv)//按值捕获,解决引用捕获超出范围的问题(引用悬空)=按值,相当于有this
			//等价于
			[this](auto tv)
		{
			cout << "m_temvalue=" << m_temvalue << endl;//7
			if (tv%m_temvalue == 0)//如果tv是temValue的倍数
			{
				return true;

			}
			return false;
		}
		);
		/*
		 * 我们会认为=是按值捕获,使我们能够访问成员变量m_temvalue,lambda表达式中使用的是m_temvalue的副本。
		 *但是如果我们在调用lambda之前删除对象的指针,//46行,结果是:
		 *m_temvalue=-572662307
		 *0
		 *也就是lambda执行的正确与否却决于pat对象是否存在,这个lambda表达式在对象存在的时候才能正确执行。
		 */
		
	}
};

int main(void)
{

	AT *pat = new AT();
	pat->addItem();
	//delete pat;
	cout << gv02[0](10) << endl;//0
	delete pat;
	
	system("pause");
	return 0;
}
/*
* (1)lambda常见陷阱_形参列表可以使用auto
* c++4中允许在lambda表达式形参列表中使用auto。//18行
* (2)lambda常见陷阱_类中成员变量捕获问题_实际上是捕获的this指针
* 明确一点:捕获这个概念,只针对在创建lambda表达式的作用域内可见的,非静态 局部变量(包括形参)
* m_temvalue不是非静态局部变量,m——temvalue是AT类的成员变量,成员变量不能被捕获到的。
* 那么为什么可以在lambda中使用m_temvalue?
* this指针指向对象本身,这里使用的[=]捕获的是this指针值。
* [=](auto tv)等价于
* [this](auto tv)
* 解决办法:将成员变量赋值到一个局部变量中,捕获局部变量的值。
* (3)
* (4)
* (5)
* (6)(7)
*/

037广义lambda捕获

#include<iostream>
#include<iostream>
#include<cstdlib>
#include<functional>
#include <vector>
#include <algorithm>
using namespace std;
//全局变量,每个元素都是function,每个元素都是参数是int,返回值是bool类型
std::vector<std::function<bool(int)>> gv02;

class AT
{
public:
	int m_temvalue = 7;
	void addItem()
	{
		gv02.push_back(// c++4中允许在lambda表达式形参列表中使用auto
				[abc=m_temvalue](auto tv)//将m_temvalue复制到闭包中来,lambda中使用的都是副本
					   //等价于
			//[this](auto tv)
		{
			cout << "m_temvalue=" << abc << endl;//7
			if (tv%abc == 0)//如果tv是temValue的倍数
			{
				return true;

			}
			return false;
		}
		);
		/*
		* 我们会认为=是按值捕获,使我们能够访问成员变量m_temvalue,lambda表达式中使用的是m_temvalue的副本。
		*但是如果我们在调用lambda之前删除对象的指针,//46行,结果是:
		*m_temvalue=-572662307
		*0
		*也就是lambda执行的正确与否却决于pat对象是否存在,这个lambda表达式在对象存在的时候才能正确执行。
		*/

	}
};

int main(void)
{
	AT *pat = new AT();
	pat->addItem();
	delete pat;//ok,可以提前删除
	cout << gv02[0](10) << endl;//0
	//delete pat;
	
	system("pause");
	return 0;
}
/*
* (1)广义lambda捕获generalized lambda capture
* c++14中引入,解决lambda表达式成员属性依赖this指针问题。

m_temvalue=7
0
请按任意键继续. . .

* 
* (3)
* (4)
* (5)
* (6)(7)
*/

038lambda中不捕获静态局部变量

#include<iostream>
#include<iostream>
#include<cstdlib>
#include<functional>
#include <vector>
#include <algorithm>
using namespace std;
std::vector<void(*)(int)>gv2;//用于存放一个int类型参数,返回值是void类型的lambda表达式

int main(void)
{
	static int temvalue = 4;
	gv2.push_back([](int value)//静态局部变量可以直接使用
	{
		cout << temvalue << endl;
		temvalue++;
	});
	
	gv2[0](12);//4
	gv2[0](123);//5
	gv2[0](123);//6
	
	system("pause");
	
	return 0;
}
/*
* (1)lambda中不捕获静态局部变量
*	捕获时间是不包括静态局部变量,也就是说静态局部变量是不能被捕获的。
*	但是可以在lambda表达式中使用静态局部变量,静态局部变量是保存在静态存储区,它的有效期是程序的运行期间。
*
*	静态变量不需要捕获,也捕获不到。但是这种对静态变量与按引用捕获效果类似。
*
*	将lambda匿名表达式存放在vector容器中,可以使用下表调用
*
*2019年12月11日19点30分
* (2)
* (3)
* (4)
* (5)
* (6)(7)
*/

猜你喜欢

转载自blog.csdn.net/qq_39885372/article/details/107580698