【C++11】lambda和可变参数模板

为了解决冗杂的函数指针(void (*p)(int a)),仿函数(通过类内重载operator())。C++11定义了lambda表达式,作为一个匿名函数对象,它可以直接再函数内部直接定义使用。以及如何像printf一样一直传入参数的问题

一.lambda表达式

书写格式

【capture-list】(parameters)mutable-> return-type {statement}

  • capture-list:捕捉列表,捕捉上下文中的变量供lambda函数使用

    • 【var】:表示值传递捕捉变量var(const变量不可修改)
    • 【=】:表示值传递方式捕捉所有父作用域中的变量(含this)
    • 【&var】:表示引用传递捕捉变量var
    • 【&】:表示引用传递捕捉所有父作用域的变量(含this)
  • parameters:参数列表,一致于普通函数的参数列表,若不需参数传递,可以省略()

  • mutable:默认情况下,lambda函数是const函数,使用该关键字取消常量性

  • ->returntype:返回值类型明确情况下,可以省略,由编译器对返回类型推导

  • {statement}:函数体

注意:语法上捕捉列表可由多个捕捉项构成,以逗号分隔。如【&a, &b】,【&,this】(this通过传值方式捕捉)。捕捉列表不允许变量重复传递,lambda表达式之间不能相互赋值

情景1:

情景2:传值捕捉,局部域的修改不影响域外的a, b。栈帧销毁

情景3:使用mutable取消常量性

小结:lambda底层是仿函数,编译器生成仿函数的类,传值传参就是在给仿函数传递,又通过调用构造函数和operator()完成任务。使用UUID作为lambda唯一标识码


可变参数模板

怎么像printf一样一直传入参数?

可变参数模板:创建接收可变参数的函数模板和类模板

  • 我们可以观察到,要使用这个模板需要将参数包扩展
  • 解参数包1

数组初始化时会推断应该开多大的数组,这时会把扩展包展开,调用函数

  • 解参数包2

使用场景

cpp 复制代码
class Date
{
public:
	Date(int year = 1, int month = 1, int day = 1)
		:_year(year)
		, _month(month)
		, _day(day)
	{
		cout << "Date构造" << endl;
	}

	Date(const Date& d)
		:_year(d._year)
		, _month(d._month)
		, _day(d._day)
	{
		cout << "Date拷贝构造" << endl;
	}

private:
	int _year;
	int _month;
	int _day;
};
template<class ...Args>
Date* Creat(Args ...args)
{
	Date* ret = new Date(args...);
	return ret;
}
int main()
{
	Date* p1 = Creat();
	Date* p2 = Creat(2023);
	Date* p3 = Creat(2023, 9);
	Date* p4 = Creat(2023, 9, 27);

	Date d(2023, 1, 1);
	Date* p5 = Creat(d);
}

emplace_back模板的可变参数+万能引用

  • 使用场景

emplace_back通过参数包使用直接构造,push_back使用构造函数出对象来,再作为将亡值,调用移动构造。对于移动构造的消耗不是很大,于是两种方法效率差不多

  • 使用情景

移动构造函数&&移动赋值重载

  • 如果没有实现移动构造函数,没有实现析构函数,拷贝构造函数,拷贝赋值重载中的任意一个。编译器会自动生成一个默认移动构造,对于内置类型成员(逐字节拷贝)。对于自定义类型成员,如果类内没有实现移动构造,就调用拷贝构造,否则调用调用移动构造函数
  • 移动赋值重载同理
  • 一般浅拷贝的类不需要自己实现上面两个函数,深拷贝的类需要自己实现

default

  • 当实现了析构函数等时,为了使用编译器默认的移动构造,需要使用default关键字
相关推荐
曹牧5 分钟前
C#:The operation has timed out
开发语言·c#
xiaoye-duck7 分钟前
《C++ 工具库实战》高性能日志 spdlog:从基础使用到工程化封装
c++·第三方库
你看我名字14 分钟前
数眼智能 Search + Reader 实战:联网问答怎样避免“搜到了,却引用错了”
android·java·开发语言
小嘉丶学长16 分钟前
Day13 · 列表与元组
linux·运维·服务器·开发语言·python
努力努力再努力wz21 分钟前
【Lua入门系列】从 C++ 迭代器到 Lua 迭代器:一文深入理解 Lua 有状态以及无状态迭代器与泛型for、闭包、ipairs、pairs 和 next
开发语言·c++·lua
努力实干28 分钟前
第二阶段 · 第 7 课:C++ 多线程与线程安全
开发语言·c++·安全
爱聊灵光的维C1 小时前
C语言初阶:关于函数设计的详细讲解和注意事项
c语言·开发语言·青少年编程·蓝桥杯·学习方法
熊猫钓鱼>_>1 小时前
上架审核常见驳回与隐私合规清单:过审前先自查这 8 条【鸿蒙心迹】
开发语言·前端·华为·华为云·harmonyos·openharmony·ai制作
SEO_juper1 小时前
Bash 交叉验证 robots.txt 和 sitemap:两个文件自相矛盾,页面永远收录不了
开发语言·python·node.js·json·bash
geovindu1 小时前
rust: Read-Write Lock Pattern
开发语言·后端·设计模式·rust·读写锁模式·同步型模式