C++11 - 3 - lambda表达式

c++

前言:

Vue框架:从项目学Vue
OJ算法系列:神机百炼 - 算法详解
Linux操作系统:风后奇门 - linux

可调用对象:

  • 含义:具有传入参数,进行处理,传出结果的功能的对象
  • 分类:
    1. 函数:
    2. 函数指针:
    3. 仿函数对象:
    4. lambda表达式:
  • 举例:
//1, 函数:
void fmin(int x, int y){
	return x<y?x:y;
}
//2,函数指针:
void func(int, int) = fmin();
func(1, 2);
//3,仿函数对象:
struct IntLess{
	bool operator()(int &x, int &y){
		return x<y?x:y; 
	}
}
IntLess(1, 2);
//4,简易lambda表达式:
auto function = [](int x, int y){
	return x<y?x:y;
};
function(1, 2);

lambda表达式:

格式:

  • 可由二/三/四/五部分构成:
//附加说明的五部分:附加关键词一般为mutable、noexcept
auto func = [](int x, int y)mutable->int{
	return x<y?x:y;
}
//完整的四部分:
auto func1 = [](int x, int y)->int{
	return x<y?x:y;
};
//省略返回类型,可自动推导返回类型
auto func2 = [](int x, int y){
	return x<y?x:y;
};
//当不需要参数时候,可省略参数
auto func3 = []{
	cout<< "hello world"<< endl;
};
  • 完整的四部分:
    1. [捕捉列表]
    2. (形参列表)
    3. ->返回值类型
    4. {函数体}
  • 附加的一部分:附加关键词
  • lambda表达式必须的两部分:[]{}
    可省略的两部分:()->

捕捉列表:

  • 含义:向lambda表达式传递参数时,()中只能传值,想要传引用或地址时,需要利用捕捉列表
  • 作用:捕捉与lambda表达式处于同一作用域下的局部变量
  • 捕捉形式:
    1. 传值捕捉
    2. 传引用捕捉
  • 捕捉范围要求:
    1. 与lambda表达式处于同一作用域
    2. 只能捕捉局部变量
    3. 对于同一变量,不可以同时捕捉值和捕捉引用
  • 捕捉形式:
    1. 引用捕捉:
      1. 捕捉当前作用域下某变量的引用:
        &a->{}
      2. 捕捉当前作用域下所有变量的引用:
        &->{}
    2. 传值捕捉:
      1. 捕捉当前作用域下某变量值:
        a->{}
      2. 捕捉当前作用域下所有变量值:
        =->{}

附加关键词:

  • mutable关键词:
    1. 作用:传值捕捉获得的变量默认是const的,想要对其进行写,需要加附件关键词mutable
    2. 放置位置:(形参)后直接附加,也就是说,使用mutable关键词时必须加(形参列表)
  • 举例:
//报错:常量不可修改
int main(){
	int x = 0;
	auto func = [=](){
		x++;
		cout<<x<<endl;
	};
	cout<<x<<endl;
}

//()mutable
int main(){
	int x = 0;
	auto func = [=]()mutable{
		x++;
		cout<<x<<endl;
	};
	cout<<x<<endl;
}

decltype表达式的本质:

  • lambda表达式本质就是仿函数类
  • 如同范围for的本质是迭代器
  • C++11中也为我们提供了推断变量类型的运算符号:decltype
auto func = [](int x, int y){
	return x<y?x:y;
};
cout<< decltype(func).name();
  • decltype和auto的区别:
    1. decltype用于需要声明变量类型的情况,如函数形参
    2. auto用于需要不声明变量类型的情况,如单纯使用

  • decltype使用:

auto func1 = []{cout<<"极简lambda"<<endl;};
auto func2 = func1;
decltype(func1) func3 = func1;

捕捉列表和参数列表对比:

实质:
  • lambda表达式转化为了仿函数类:
    1. 捕捉列表转化为了类内成员变量
    2. 参数转化为了类内函数参数
作用域:
  • 形参列表() + mutable,传参来源可以是任何变量,当然不加mutable范围不变,写权限消失
  • 捕捉列表捕捉的对象只能是同作用域下的局部变量
  • 当对同作用域下的局部变量操作时,()+mutable和[]效果相同

调用对象对比:

lambda:

  • lambda表达式相对函数/函数指针/仿函数对象来说写作更快捷,

    适用于编写依据类的不同字段,对类的对象排序,类似这样的代码

  • 下面给出一个商品类,求分别按照商品价格/评分/名称,对商品对象进行排序:

  • 商品类:

class Goods{
	private:
		int price;
		double evaluate;
		char* name;
	public:
		//八大默认函数,自动补全。
		Goods(int _price, double _evaluete, char* _name){
			price = _price;
			evaluete = _evaluete;
			name = _name;
		}
};
  • 商品排序 - 基于lambda表达式:
vector<Goods> v{{1, 1.0, "a"}, {2, 2.0, "b"}, {3, 3.0, "c"}, {4, 4.0, "d"}};
sort(v.begin(), v.end(), [](Goods &a, Goods &b){
		return a.price > b.price;
	});
sort(v.begin(), v.end(), [](Goods &a, Goods &b){
		return a.price < b.price;
	});
sort(v.begin(), v.end(), [](Goods &a, Goods &b){
		return a.evaluete > b.evaluete;
	});
sort(v.begin(), v.end(), [](Goods &a, Goods &b){
		return a.evaluete < b.evaluete;
	});
sort(v.begin(), v.end(), [](Goods &a, Goods &b){
		return strcmp(a.name, b.name);
	});
sort(v.begin(), v.end(), [](Goods &a, Goods &b){
		return -1*strcmp(a.name, b.name);
	});

函数指针:

  • 商品排序 - 基于函数/函数指针:
bool ComparePriceLess(Goods &a, Goods &b){
	return a.price < b.price;
}
bool ComparePriceMore(Goods &a, Goods &b){
	return a.price < b.price;
}
bool CompareEvaluateLess(Goods &a, Goods &b){
	return a.price < b.price;
}
bool CompareEvaluateMore(Goods &a, Goods &b){
	return a.price < b.price;
}
bool CompareNameLess(Goods &a, Goods &b){
	return a.price < b.price;
}
bool CompareNameMore(Goods &a, Goods &b){
	return a.price < b.price;
}
vector<Goods> v{{1, 1.0, "a"}, {2, 2.0, "b"}, {3, 3.0, "c"}, {4, 4.0, "d"}};
sort(v.begin(), v.end(), ComparePriceLess);
sort(v.begin(), v.end(), ComparePriceMore);
sort(v.begin(), v.end(), CompareEvaluateLess);
sort(v.begin(), v.end(), CompareEvaluateMore);
sort(v.begin(), v.end(), CompareNameLess);
sort(v.begin(), v.end(), CompareNameMore);
}

仿函数对象:

  • 商品排序 - 基于仿函数:
struct ComparePriceLess{
	bool operator()(Goods &a, Goods &b){
		return a.price < b.price;
	}
};
struct ComparePriceMore){
	bool operator()(Goods &a, Goods &b){
		return a.price > b.price;
	}
};
struct CompareEvaluateLess{
	bool operator()(Goods &a, Goods &b){
		return a.evaluate < b.evaluate;
	}
};
struct CompareEvaluateLess{
	bool operator()(Goods &a, Goods &b){
		return a.evaluate > b.evaluate;
	}
};
struct CompareNameLess{
	bool operator()(Goods &a, Goods &b){
		return -1*strcmp(a.name, b.name);
	}
};
struct CompareNameLess{
	bool operator()(Goods &a, Goods &b){
		return strcmp(a.name, b.name);
	}
};
vector<Goods> v{{1, 1.0, "a"}, {2, 2.0, "b"}, {3, 3.0, "c"}, {4, 4.0, "d"}};
sort(v.begin(), v.end(), ComparePriceLess());
sort(v.begin(), v.end(), ComparePriceMore());
sort(v.begin(), v.end(), CompareEvaluateLess());
sort(v.begin(), v.end(), CompareEvaluateMore());
sort(v.begin(), v.end(), CompareNameLess());
sort(v.begin(), v.end(), CompareNameMore());
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

starnight531

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值