9-8 lambda表达式,for_each、find_if简介(未归类知识点)

028lambda表达式和捕获列表

#include<iostream>
#include<cstdlib>

using namespace std;

class CT
{
public:
	int m_i;
	void myFunction(int x,int y)
	{
		auto mylambda01 = [this]()//=或者&默认就有this访问
		{
			return m_i;//因为前面已经有this,访问合法
		};
	}
};

int main(void)
{
	auto f=[](int a=45)->int//后置返回类型  ,并且擦拭农户可以有默认值
	{
		return a + 1;
	};//这里必须有分号
	//调用lambda表达式
	cout << f(12) << endl;//13

	static int numnber01 = 12;
	auto f1=[]()
	{
		return  numnber01;//需要捕获前面定义的number01,可以直接捕获静态局变量
	};
	//[&]
	int number02 = 02;
	auto f2=[&]()
	{
		number02++;
		return number02;
	};
	cout << f2() << endl;//3
	//2.3 [=]
	auto f3 = [=]()
	{
		cout << number02 << endl;
		//number02 = 12;//error 不能修改
	};
	//2.4[this]
	CT ct;
	ct.myFunction(3, 4);

	//2.5[变量名字1,变量名字2...]
	int number03 = 3;
	auto f4 = [number02]()
	{
		cout << number02 << endl;
		//cout << number03 << endl;//error
	};
	system("pause");
	return 0;
}

/*lambda表达式和捕获列表
* (1)c++11中的新特性,也是一种可调用对象
* lambda表达式,定义了一个匿名函数,并且可以捕获一定范围内的变量。[]--标志是一个lambad表达式
* 特点:
*	1.是个匿名函数,也可以理解为“可调用代码单元”,或者“未命名的内联函数”。
*	2.也有一个返回类型,一个参数列表,一个函数体
*	3.与函数不同的是,lambda可以在函数内部定义,常规函数不允许。
*格式:
*auto[捕获列表](参数列表)->返回类型后置
*{函数体}
*这是一个返回类型后置语法,lambda表达式的返回类型后置是强制要求,语法就是这么要求的。
*因为很多时候lambda表达式返回值特别明显,所以允许lambda表达式返回值类型省略。编译器可以自动推导。
*
*lambda表达式参数列表可以有默认值。
*
*1.2参数列表中没有参数的时候,参数列表可以省略,甚至()可以省略,如下格式都合法:
*auto f1=[](){return 1;}
*auto f2=[]{return 1;}
*
*1.3捕获列表[]和函数体{}不能省略。
*
*1.4lambda调用方法和普通函数相同,都是使用()这种函数调用运算符。
*1.5lambda表达式可以不返回任何类型给你,不返回任何类型就是void类型。
*auto f3=[]{};//ok
*1.6函数体末尾的分号不能省略。
* (2)捕获列表[]--通过捕获列表来捕获一定范围内的变量
*	2.1[]空表示不捕获任何变量,但是不包括静态局部变量。
*	2.2[&] 表示以"引用"方式捕获外部作用域中的所有变量。
*	2.3[=]表示以“值传递”的方式捕获外部变量,只能使用,修改不了外部变量。
*	2.4[this]一般用于类中,捕获当前类中this指针,让lambda表达式有和当前类成员函数具有同样的
*		访问权限。如果中括号中已经使用&,或者=,就已经默认使用了this,就是让lambda使用当前类中的成员变量。
*		用在类中定义lambda匿名函数
*	2.5[变量名字1,变量名字2...]多个变量使用逗号分开,按照值捕获列出的变量,没有列出的变量,不捕获。
*	2.6[&变量名字1,&量名字2...]用引用捕获多个变量,同时不捕获没有蕾出的变量
*	2.7[=,&变量名]  按值捕获所有外部变量,同时按应用捕获&列出的变量。=必须写在开头位置,第一个位置表示默认捕获方式。
*	2.8[&,变量名字] 按引用捕获外部变量,同时按值捕获指定的外部变量。
*总结:lambda表达式对于外部捕获控制特别细致。
*	
* (3)
* (4)
* (5)
* (6)(7)
* 2019年12月11日13点22分
*/

029lambda表达式延迟调用易出错细节分析

#include<iostream>
#include<cstdlib>

using namespace std;

int main(void)
{
	int x = 5;
	auto f1=[=]()//在捕获的这一时刻,x的值已经复制到lambda里面了
	{
		return x;
	};
	x = 10;
	cout << f1() << endl;//5,不是我们认为的10.
	//凡是按值捕获的外部变量,在lambda表达式定义的时刻就被赋值一份存储在lambda表达式中,这里输出的是lambda
	//表达式内部的值输出。这里的解决办法就是使用&引用
	system("pause");
	return 0;
}
/*
* (1)lambda表达式延迟调用易出错细节分析
* 从这个例子理解lambda的延迟调用
* 
* (2)
* (3)
* (4)
* (5)
* (6)(7)
*/

030ambda表达式中的mutable

#include<iostream>
#include<cstdlib>

using namespace std;

int main(void)
{
	int x = 10;
	auto f1 = [=]()mutable //加上mutable可以更改x的值,虽然是按值捕获的x
	{
		x = 234;
	};
	
	
	system("pause");
	return 0;
}
/*
* (1)ambda表达式中的mutable
* mutable容易改变的,易变的
* 不管是不是一个const属性的变量,加上mutable就可以修改它的值。
* (2)
* (3)
* (4)
* (5)
* (6)(7)
*/

031lambda表达式的类型和存储_创建匿名类对象,捕获列表当作类成员属性

#include<iostream>
#include<cstdlib>
#include<functional>


using namespace std;

int main(void)
{
	auto f1 = [] {};//f1就相当于一个未命名的类 类型对象

	int x = 5;
	auto f2 = [=]()
	{
		return x;
	};//f2要生成一个类类型变量,这些捕获的外部变量要在类内部作为成员变量存在。

	//lambda和function结合使用例子
	std::function<int(int)>f3 = [](int value)->int
	{
		value++;
		return value;
	};
	cout << f3(15) << endl;//16

	std::function<int(int)>f4 = std::bind(
		[](int value)
	{
		return value + 1;
		
	},placeholders::_1
	);
	//bind第一个参数是可调用对象或者函数指针,第二个参数是函数参数
	cout << f4(23) << endl;//24

	//捕获列表为空的lambda表达式,可以转换成一个普通的函数指针。
	using funcpType = int(*)(int);//定义一个函数指针类型
	funcpType fp = [](int value) {return value + 1; };
	cout << fp(123) << endl;//124
	
	system("pause");
	return 0;
}
/*
* (1)lambda表达式的类型和存储
* c++11中lambda表达式的类型被成为“闭包类型(closure type)”。
* 闭包--函数内部的函数(可调用对象),本质上就是lambda表达式创建的运行时期的对象。
* lambda表达式是一种比较特殊的,匿名的,类 类型(闭包类)的对象。
* 我们也可以认为他是一个带有operator()类型的对象。也就是仿函数(函数对象)
*
* 所以我们可以使用std::function  std::bind来保存和调用lambda表达式,每个lambda都会
* 触发编译器生成一个独一无二的类类型。
* 
* lambda表达式这种语法我们可以就地定义匿名函数,就地封装短小的功能闭包。
* 
* (2)语法糖的概念
*	就是一种便捷写法
*	int a[4];
*	a[0]=5;//编译器内部的写法*(a+0)=5;
*	语法糖的目的就是让我们写的代码更加简单,容易理解,减少代码出错的机率。
*	语法糖是基于语言现有的特性,构建出一个东西,使用起来更简单,但是没有增加语言的原有功能。
*	lambda表达式可以堪称定义仿函数闭包(函数中函数)的语法糖。
* (3)
* (4)
* (5)
* (6)(7)
*/

032for_each()例子

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

void myFunction(int i)
{
	cout << "i=" << i << endl;
}

int main(void)
{
	vector<int>myVector = { 10,20,30,40 };
	for_each(myVector.begin(), myVector.end(), myFunction);//起始迭代器,结束迭代器,操作
	
	system("pause");
	return 0;
}
/*
* for_each()是个函数模板
* (2)
* (3)
* (4)
* (5)
* (6)(7)
*/

033for_each()使用lambda表达式

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

void myFunction(int i)
{
	cout << "i=" << i << endl;
}

int main(void)
{
	vector<int>myVector = { 10,20,30,40 };
	int iSum = 0;
	for_each(myVector.begin(), myVector.end(), [&iSum](int value)
	{
		cout << "value=" << value << endl;
		iSum += value;
	});
	cout << "iSum=" << iSum << endl;//100
	system("pause");
	return 0;
}
/*
* for_each()使用lambda表达式
* (2)
* (3)
* (4)
* (5)
* (6)(7)
*/

034find_if()用法

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

int main(void)
{
	vector<int>myVector = { 10,20,30,40 };
	auto result = find_if(myVector.begin(), myVector.end(), [](int value)
	{
		cout << "value=" << value << endl;
		if (value>20)
		{
			return true;//返回true停止遍历。
		}
		return false;//只要返回false就一直遍历,遍历完毕为止。一直到返回true或者遍历完毕位置
		//find_if第三个参数这个可调用对象返回true,find_if就停止遍历。
		//find_if返回一个迭代器,指向第一个满足条件的元素,如果不存在这样的元素,则这个迭代器会指向myVector.end()
	});
	system("pause");
	return 0;
}
/*
* (1)find_if()
* 函数模板,按条件查找,按照第三个参数给定的函数对象查找
* 
* (2)总结:多学习别人写的代码学习find_if()用法
* 
* (3)
* 
* (4)
* 
* (5)
* 
* (6)
* 
* (7)
*/

猜你喜欢

转载自blog.csdn.net/qq_39885372/article/details/107580302
9-8