【C++】第二十七节—C++11(下) | 可变参数模版+新的类功能+STL中一些变化+包装器

【C++】第二十七节—C++11(下) | 可变参数模版+新的类功能+STL中一些变化+包装器

Hi,好久不见,我是云边有个稻草人,偶尔中二的C++领域博主与你分享专业知识U·ェ·U

《C++》本篇文章所属专栏—持续更新中—欢迎订阅~

目录

五、可变参数模版

1. 基本语法及原理

2. 包扩展

方式一

方式二

3. empalce系列接口

六、新的类功能

1. 默认的移动构造和移动赋值

2. 成员变量声明时给缺省值

3. defult和delete

4. final与override

七、STL中一些变化

八、包装器

1. function

2. bind


正文开始——

五、可变参数模版

1. 基本语法及原理
  • C++11支持可变参数模板,也就是说支持可变数量参数的函数模板和类模板,可变数目的参数被称 为参数包,存在两种参数包:模板参数包,表示零或多个模板参数;函数参数包:表示零或多个函 数参数。
  • template void Func(Args... args) {}
  • template void Func(Args&... args) {}
  • template void Func(Args&&... args) {}
  • 我们用省略号来指出一个模板参数或函数参数的表示一个包,在模板参数列表中,class...或 typename...指出接下来的参数表示零或多个类型列表;在函数参数列表中,类型名后面跟...指出 接下来表示零或多个形参对象列表;函数参数包可以用左值引用或右值引用表示,跟前面普通模板 一样,每个参数实例化时遵循引用折叠规则。
  • 可变参数模板的原理跟模板类似,本质还是去实例化对应类型和个数的多个函数。
  • 这里我们可以使用sizeof...运算符去计算参数包中参数的个数。
template <class ...Args> void Print(Args&&... args) { cout << sizeof...(args) << endl; } int main() { double x = 2.2; Print(); // 包里有0个参数 Print(1); // 包里有1个参数 Print(1, string("xxxxx")); // 包里有2个参数 Print(1.1, string("xxxxx"), x); // 包里有3个参数 return 0; } // 原理1:编译本质这里会结合引用折叠规则实例化出以下四个函数 void Print(); void Print(int&& arg1); void Print(int&& arg1, string&& arg2); void Print(double&& arg1, string&& arg2, double& arg3); // 原理2:更本质去看没有可变参数模板,我们实现出这样的多个函数模板才能支持 // 这里的功能,有了可变参数模板,我们进一步被解放,他是类型泛化基础 // 上叠加数量变化,让我们泛型编程更灵活。 void Print(); template <class T1> void Print(T1&& arg1); template <class T1, class T2> void Print(T1&& arg1, T2&& arg2); template <class T1, class T2, class T3> void Print(T1&& arg1, T2&& arg2, T3&& arg3); // ...
2. 包扩展
  • 对于一个参数包,我们除了能计算他的参数个数,我们能做的唯一的事情就是扩展它,当扩展一个包时,我们还要提供用于每个扩展元素的模式,扩展一个包就是将它分解为构成的元素,对每个元素应用模式,获得扩展后的列表。我们通过在模式的右边放一个省略号(...)来触发扩展操作。底层的实现细节如图一所示。见方式一
  • C++还支持更复杂的包扩展,直接将参数包依次展开依次作为实参给一个函数去处理。见方式二

不支持用下面的方式去进行包扩展

// 可变模板参数 // 参数类型可变 // 参数个数可变 // 打印参数包内容 template <class ...Args> void Print(Args... args) { // 可变参数模板编译时解析 // 下面是运行获取和解析,所以不支持这样用 cout << sizeof...(args) << endl; for (size_t i = 0; i < sizeof...(args); i++) { cout << args[i] << " "; } cout << endl; }

见下面使用递归的一种包扩展的方式

方式一
void ShowList() { // 编译器时递归的终止条件,参数包是0个时,直接匹配这个函数 cout << endl; } template <class T, class ...Args> void ShowList(T x, Args... args) { cout << x << " "; // args是N个参数的参数包 // 调用ShowList,参数包的第一个传给x,剩下N-1传给第二个参数包 ShowList(args...); } // 编译时递归推导解析参数 template <class ...Args> void Print(Args... args) { ShowList(args...); } int main() { Print(1, string("xxxxx"), 2.2); return 0; } // 调用时 // 本质编译器将可变参数模板通过模式的包扩展, // 编译器推导的以下三个重载函数函数 //void ShowList(double x) //{ // cout << x << " ";ShowList(); //} //void ShowList(string x, double z) //{ // cout << x << " "; // ShowList(z); //} //void ShowList(int x, string y, double z) //{ // cout << x << " "; // ShowList(y, z); //} //void Print(int x, string y, double z) //{ // ShowList(x, y, z); //}

对上面包扩展的过程进行解析

图一
方式二
template <class T> const T & GetArg(const T & x) { cout << x << " "; return x; } template <class ...Args> void Arguments(Args... args) { } template <class ...Args> void Print(Args... args) { // 注意GetArg必须返回或者到的对象,这样才能组成参数包给Arguments Arguments(GetArg(args)...); } // 本质可以理解为编译器编译时,包的扩展模式 // 将上面的函数模板扩展实例化为下面的函数 // 是不是很抽象,C++11以后,只能说委员会的大佬设计语法思维跳跃得太厉害 //void Print(int x, string y, double z) //{ //Arguments(GetArg(x), GetArg(y), GetArg(z)); //} int main() { Print(1, string("xxxxx"), 2.2); return 0; }

稍稍解释一下:

3. empalce系列接口
  • template void emplace_back (Args&&... args);
  • template iterator emplace (const_iterator position, Args&&... args);
  •  C++11以后STL容器新增了empalce系列的接口,empalce系列的接口均为模板可变参数,功能上兼容push和 insert 系列,但是empalce还支持新玩法,假设容器为container,empalce还支持直接插入构造T对象的参数,这样有些场景会更高效一些,可

Read more

“现在的AI就像1880年的笨重工厂!”微软CSO斯坦福泼冷水:别急着造神

“现在的AI就像1880年的笨重工厂!”微软CSO斯坦福泼冷水:别急着造神

大模型仍未对上商业的齿轮? 编译 | 王启隆 来源 | youtu.be/aWqfH0aSGKI 出品丨AI 科技大本营(ID:rgznai100) 现在的硅谷,空气里都飘着一股“再不上车就晚了”的焦躁感。 最近 OpenClaw 风头正旺,强势登顶 GitHub,终结了 React 神话,许多人更是觉得“AI 自己干活赚钱”的日子就在明天了。 特别是在斯坦福商学院(GSB)这种地方,台下坐着的都是成天琢磨怎么用下一个技术风口搞个独角兽出来的狠人。 微软的首席科学官(CSO)Eric Horvitz 被请到了这个几乎全美最想用 AI 变现的礼堂里。作为从上世纪 80 年代就开始搞 AI 的绝对老炮、也是微软技术底座的“扫地僧”,这位老哥并没有顺着台下的胃口,去吹捧下个月大模型又要颠覆什么行业,而是兜头给大家浇了一盆带点学术味的冷水。 他讲了一个挺有画面感的比喻:大家都在聊

By Ne0inhk
Godot被AI代码“围攻”!维护者崩溃发声:“不知道还能坚持多久”

Godot被AI代码“围攻”!维护者崩溃发声:“不知道还能坚持多久”

整理 | 郑丽媛 出品 | ZEEKLOG(ID:ZEEKLOGnews) 当大模型能在几秒钟内生成一段“看起来像那么回事”的补丁时,开源社区却开始付出另一种代价。 最近,开源游戏引擎 Godot 的核心维护团队公开吐槽:他们正被大量“AI 生成的低质量代码”淹没。那些代码往往结构完整、注释齐全、描述洋洋洒洒,但真正的问题是——提交者可能并不理解自己交上来的内容。 这件事,并不是简单的“有人偷懒用 AI 写代码”。它正在触及开源协作最核心的东西:信任。 一场悄无声息的“AI 洪水” 事情的导火索来自一条 Bluesky 讨论帖。 Godot 主要维护者之一、同时也是 Godot 商业支持公司 W4 Games 联合创始人的 Rémi Verschelde 表示,所谓的“AI slop”

By Ne0inhk
诺奖得主辛顿最新访谈:1 万个 AI 可以瞬间共享同一份“灵魂”,这就是为什么人类注定被超越

诺奖得主辛顿最新访谈:1 万个 AI 可以瞬间共享同一份“灵魂”,这就是为什么人类注定被超越

当宇宙级的“嘴炮”遇到降维打击。 编译 | 王启隆 来源 | youtu.be/l6ZcFa8pybE 出品丨AI 科技大本营(ID:rgznai100) 打开最新一期知名播客 StarTalk 的 YouTube 评论区,最高赞的一条留言是这样写的: “我长这么大,第一次看到尼尔·德葛司·泰森(Neil deGrasse Tyson)在一档节目里几乎全程闭嘴,像个手足无措的小学生一样乖乖听讲。” 作为全美最知名的天体物理学家,泰森平时的画风是充满激情、喋喋不休、用宇宙的宏大来震撼嘉宾。但这一次,坐在他对面的那位满头银发、带着温和英音的英国老人,仅仅用最平淡的语气,就让整个演播室陷入了数次令人窒息的沉默。 这位老人是 Geoffrey Hinton。深度学习三巨头之一,2024 年诺贝尔物理学奖得主,被公认为“AI 教父”。 对经常阅读 Hinton 演讲的我来说,这也是比较新奇的一幕—

By Ne0inhk
48小时“烧光”56万!三人创业团队濒临破产,仅因Gemini API密钥被盗:“AI账单远超我们的银行余额”

48小时“烧光”56万!三人创业团队濒临破产,仅因Gemini API密钥被盗:“AI账单远超我们的银行余额”

整理 | 苏宓 出品 | ZEEKLOG(ID:ZEEKLOGnews) 「仅过了 48 小时,一笔 8.2 万美元的天价费用凭空出现,较这家小型初创公司的正常月费暴涨近 46000%。」 这不是假设的虚幻故事,而是一家墨西哥初创公司正在经历的真实危机。 近日,一位名为 RatonVaquero 的开发者在 Reddit 发帖求助称,由于他的 Gemini API 密钥被盗用,原本每月仅约 180 美元(约 1242 元)的费用,在短短 48 小时内暴涨到 82,314.44 美元(约 56.8 万元)。对于这家只有三名开发者的小型创业团队来说,这笔突如其来的账单,几乎等同于灭顶之灾。 “我现在整个人都处在震惊和恐慌之中。”RatonVaquero

By Ne0inhk