C++11的更新介绍(新的类功能、可变参数模板)

🪐🪐🪐欢迎来到程序员餐厅💫💫💫

          主厨:邪王真眼

主厨的主页:Chef‘s blog  

所属专栏:c++大冒险

总有光环在陨落,总有新星在闪烁


新的类功能

默认成员函数:

  •  原来C++类中有6个默认成员函数

  1. 构造函数
  2. 析构函数
  3.  拷贝构造函数
  4. 拷贝赋值重载
  5. 取地址重载
  6. const 取地址重载
没印象的朋友可以回顾一下往期内容:
C++6个默认构造函数及const函数

  • C++11新增移动构造函数和移动赋值运算符重载

默认移动构造和默认移动赋值的拷贝方式

  1. 默认生成的移动构造函数,对于内置类型成员会执行逐成员按字节拷贝,自定义类型成员,则需要看这个成员是否实现移动构造,如果实现了就调用移动构造,没有实现就调用拷贝构造。
  2. 默认生成的移动构造函数,对于内置类型成员会执行逐成员按字节拷贝,自定义类型成员,则需要看这个成员是否实现移动赋值,如果实现了就调用移动赋值,没有实现就调用拷贝赋值。

移动构造函数和移动赋值运算符重载生成条件

  1. 如果没有自己实现移动构造函数,且没有实现析构函数 、拷贝构造、拷贝赋值重载中的任意一个。那么编译器会自动生成一个默认移动构造。
  2. 如果没有自己实现移动赋值重载函数,且没有实现析构函数 、拷贝构造、拷贝赋值重载中的任意一个,那么编译器会自动生成一个默认移动赋值。

 为什么设计这样的条件: 

当涉及深拷贝时,我们 从我们之前实现的移动拷贝可以得知,对于深拷贝的移动构造,是所包含的资源转移要有程序员决定,

即:深拷贝的移动构造要由程序员决定,浅拷贝不用,所以通过上面的条件确定当前类是深拷贝还是浅拷贝


类成员变量初始化

C++11 允许在类定义时给成员变量初始缺省值,默认生成构造函数会使用这些缺省值初始化,这
个我们在雷和对象默认就讲了,这里就不再细讲了,直接上代码。
class A
{int a = 0;//直接给缺省值,如果在构造函数没有处理a的值,那他就是我们所给的缺省值static int b;//静态成员变量不能给缺省值string s = "abc";//自定义类型也可以给缺省值
};

强制生成默认函数的关键字default:

C++11可以让你更好的控制要使用的默认函数。假设你要使用某个默认的函数,但是因为一些原
因这个函数没有默认生成。比如:我们提供了拷贝构造,就不会生成移动构造了,那么我们可以
使用default关键字显示指定移动构造生成。
class Person
{
public:Person(const char* name = "", int age = 0):_name(name), _age(age){}Person(const Person& p):_name(p._name),_age(p._age){}Person(Person&& p) = default;
private:bit::string _name;int _age;
};
int main()
{Person s1;Person s2 = s1;Person s3 = std::move(s1);return 0;
}

注意: 默认成员函数都可以用default关键字强制生成,包括移动构造和移动赋值。


禁止生成默认函数的关键字delete

如果能想要限制某些默认函数的生成,在C++98中,是该函数设置成private,并且只声明补丁
已,这样只要其他人想要调用就会报错。在C++11中更简单,只需在该函数声明加上=delete即
可,该语法指示编译器不生成对应函数的默认版本,称=delete修饰的函数为删除函数。
class Person
{
public:Person(const char* name = "", int age = 0):_name(name), _age(age){}Person(const Person& p) = delete;
private:bit::string _name;int _age;
};
int main()
{Person s1;Person s2 = s1;Person s3 = std::move(s1);return 0;
}

final与override关键字

  • final修饰虚函数,表示该虚函数不能再被重写

class Person
{virtual int number()final{return 0;}
};
class Student :public Person
{virtual int number(){return 0;}
};
  • final修饰类,该类不能被继承

class Person final
{int a=0;
};
class Student :public Person
{};
  • override

如果派生类在虚函数声明时使用了override关键字,那么该函数必须重载其基类中的同名函数,否则代码将无法通过编译,如下:

派生类中由于fun1没有const修饰,导致没有实现虚函数重写,此时编译器会报错

class Base
{
public:virtual void fun1() const{;}};class Derived : public Base
{
public:virtual void fun1() override{;}};



可变参数模板

可变参函数模板定义:

C++11的新特性可变参数模板能够让您创建可以接受可变参数的函数模板和类模板。
下面就是一个基本可变参数的函数模板
// Args是一个模板参数包,args是一个函数形参参数包
// 声明一个参数包Args...args,这个参数包中可以包含0到任意个模板参数。
template <class ...Args>
void ShowList(Args... args)
{}
上面的参数args前面有省略号,所以它就是一个可变模版参数,我们把带省略号的参数称为“参数
包”,它里面包含了0到N(N>=0)个模版参数。
模板参数包Args和函数形参参数包args的名字可以任意指定,并不是说必须叫做Args和args,判断是否为参数包的主要关键在【省略号】

可变参函数模板使用:

template<class ...Args>
void  A(Args ...args)
{;
}
int main()
{A(0);A('a');A("aa", 'a', 0);
}

但是,我们如何解析参数包中的内容呢?

我们无法直接获取参数包args中的每个参数的, 只能通过展开参数包的方式来获取参数包中的每个参数。但语法不支持使用args[i]这样方式获取可变参数

template<class ...Args>
void ShowList(Args... args)
{for (int i = 0; i < sizeof...(args); i++){cout << args[i] << " ";}cout << endl;
}

递归函数方式展开参数包

展开函数

我们每调一次ShowList函数,就会把第一个参数T val打印,然后把args参数包传给下一次调用的ShowList,接着参数包里的第一个参数会被下一个函数的T类型接受,剩下的会被args接受,如此递归下去,每次剥离出参数包中的一个参数,直到参数包中的所有参数都被取出来。

template<class T,class ...Args>
void ShowList(T val, Args ...args)
{cout << val << endl;ShowList(args);
}

 递归结束:

根据函数匹配原则我们设计一个函数模板,只有一个参数,这样当参数报只剩一个参数时就会跳出循环进入该函数,从而结束递归

template<class T>
void ShowList(T val)
{cout << val << endl;
}

 逗号表达式展开参数包

这种方式,不需要通过递归终止函数,是直接在expand函数体中展开的, printarg不是一个递归终止函数,只是一个处理参数包中每一个参数的函数。逗号表达式会按顺序执行逗号前面的表达式。
expand函数中的逗号表达式先执行 printarg(args),再得到逗号表达式的结果0。{(printarg(args), 0)...}将会展开成((printarg(arg1),0),(printarg(arg2),0), (printarg(arg3),0), etc... ),最终会创建一个元素值都为0的数组。由于是逗号表达式,在创建数组的过程中会先执行逗号表达式前面的部分printarg(args) 打印出参数,也就是说在构造int数组的过程中就将参数包展开了
template <class T>
void PrintArg(T t)
{cout << t << " ";
}
//展开函数
template <class ...Args>
void ShowList(Args... args)
{int arr[] = { (PrintArg(args), 0)... };cout << endl;
}
int main()
{ShowList(1);ShowList(1, 'A');ShowList(1, 'A', std::string("sort"));return 0;
}

可变参数模板的应用:emplace系列函数

emplace系列的接口,支持模板的可变参数,并且万能引用。
  • emplace与insert对比

我们先分析下面的代码:
对于emplace_back:参数为10和‘a’,根据可变参数模板的性质,他们会直接作为参数传入到list的函数中,再去构建节点中的pair<>,直接构造
对于push_back:参数50,‘e’,会先构造一个临时变量pair<>,接着调用转移构造去构建节点中的pair<>,先是构造函数,在移动拷贝
int main()
{std::list< std::pair<int, char> > mylist;mylist.emplace_back(10, 'a');mylist.push_back({ 50, 'e' });return 0;
}
即:emplace只拷贝了一次,但push_back先拷贝在移动拷贝
但是由于深拷贝中移动拷贝效率高,所以二者差距不明显
  • emplace系列接口相对insert的优势

emplace系列真正的优势在于浅拷贝的类

因为对于深拷贝的且实现了移动构造的类来说,移动构造代价很小,emplace的优势显现不出来。

浅拷贝效率低,则可以认为emplace_back节省了一次拷贝构造的时间,例如日期类

class Date
{
public://构造Date(int year, int month, int day):_year(year), _month(month), _day(day){cout << "Date(int year, int month, int day)" << endl;}Date(Date &d):_year(d._year), _month(d._month), _day(d._day){cout << "Date(Date&d)" << endl;}Date(Date&& d):_year(d._year), _month(d._month), _day(d._day){cout << "Date(Date&&d)" << endl;}
private:int _year = 1;int _month = 1;int _day = 1;
};
int main()
{list<Date> lt1;lt1.push_back({ 2024,3,30 });cout << "=============================================" << endl;lt1.emplace_back(2024, 3, 30);return 0;
}


总结

  1. emplace接口使用需要直接传入参数包才能体现其价值,因为emplace真正高效的情况是传入参数包的时候,直接通过参数包构造出对象,避免了中途的一次拷贝。

  2. emplace对于深拷贝的且实现了移动构造的类意义不大,因为移动构造的代价很小,emplace系列接口对于浅拷贝的类有可观的效率提升

  3. 使用emplace应该直接传参数包,因为如果传入的是对象(不管有名还是匿名),那么emplace系列接口的效率和insert接口的效率一样(都是调用拷贝构造)


    🥰创作不易,你的支持对我最大的鼓励🥰

    🪐~ 点赞收藏+关注 ~🪐

    e3ff0dedf2ee4b4c89ba24e961db3cf4.gif

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/812629.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《师兄啊师兄》:玄机科技打造国漫新高峰,IP运营再显神力

在这个国漫蓬勃发展的时代&#xff0c;玄机科技再次以其超凡的制作水准和出色的IP运营能力&#xff0c;为我们带来了一部国漫新经典——《师兄啊师兄》。这部作品不仅在画面、剧情上达到了行业新高度&#xff0c;更在IP运营上展现出了其强大的实力与前瞻性。 《师兄啊师兄》的画…

构建智能连接的未来:物联网平台系统架构解析

随着科技的不断进步和互联网的普及&#xff0c;物联网&#xff08;Internet of Things, IoT&#xff09;已成为连接世界的新方式。物联网平台作为实现物联网应用的核心基础设施&#xff0c;其系统架构的设计和实施至关重要。本文将深入探讨物联网平台系统架构的关键要素和最佳实…

【七 (2)FineBI-平台新增用户留存分析】

目录 文章导航一、字段解释1、用户平台登录信息表格2、用户平台激活信息表格 二、需求三、操作步骤1、建立用户平台登录信息表格和用户平台激活信息表格的关联关系2、将用户平台激活信息表格的激活日期添加到用户平台登录信息表格3、新增公式列&#xff0c;计算激活时间和登录时…

P4119 [Ynoi2018] 未来日记

它来了&#xff01; 分析一下第一个操作&#xff0c;不是写过嘛&#xff0c;并查集 分析一下第二个操作&#xff0c;二分套二分答案 拿下了这题 仔细分析&#xff0c;貌似时间复杂度是错的 我们考虑块套块 时间复杂度 对1e5的值域进行分块 求k值我们可以先找是第几个块&…

word并排比较

Word并排比较是一种在Microsoft Word文档中同时显示两个文本内容并进行比较的功能。这种比较通常用于查看文档的不同版本之间的差异&#xff0c;或者比较两个不同来源的文本内容。 在Word中进行并排比较通常可以通过以下步骤实现&#xff1a; 通过这种方式&#xff0c;Word的并…

2024阿里云学生服务器申请图文全流程,学生机免费续费攻略

2024年阿里云学生服务器免费申请&#xff0c;完成学生认证可以领取1个月免费学生机&#xff0c;完成任务可以再免费学费6个月时长&#xff0c;还可以领取高校计划学生300元无门槛优惠代金券&#xff0c;阿里云服务器网aliyunfuwuqi.com整理2024年最新阿里云大学生服务器申请入口…

8路HDMI+8路AV高清视频流媒体编码器JR-3218HD

产品简介&#xff1a; JR-3218HD高清音视频编码产品支持8路高清HDMI音视频采集功能&#xff0c;8路AV视频采集功能&#xff0c;8路3.5MM独独立音频接口采集功能。编码输出双码流H.264格式&#xff0c;音频MP3/AAC格式。编码码率可调&#xff0c;画面质量可控制。支持HTTP/RTSP…

引人共鸣的情感视频素材在哪找?今天看这五个网站

朋友们好啊&#xff0c;最近是不是不少人都在发愁啊&#xff0c;优秀创作者做视频用的视频素材哪来的啊&#xff1f;今天我为朋友们准备了几个优秀的视频素材网站&#xff0c;让你们做视频不再缺少素材&#xff0c;然后还有几个辅助创作的工具&#xff0c;都是你们需要的&#…

电源——BUCK详解

目录 BUCK电路工作原理3种工作模式 BUCK电路实操PCB如何降低EMI和EMC及注意事项 BUCK电路工作原理 如图&#xff0c;给一个一定频率的PWM波控制Q1&#xff0c;使得输入电压不停的导通断开&#xff0c;达到降压的目的。 输入电压 * 占空比 输出电压 非隔离 输入与输出的极性相同…

CSS导读 (复合选择器 上)

&#xff08;大家好&#xff0c;今天我们将继续来学习CSS的相关知识&#xff0c;大家可以在评论区进行互动答疑哦~加油&#xff01;&#x1f495;&#xff09; 目录 二、CSS的复合选择器 2.1 什么是复合选择器 2.2 后代选择器(重要) 2.3 子选择器(重要) Questions 小提…

贝乐虎儿歌v6.8.0解锁高级版亲子学习儿歌

软件介绍 贝乐虎儿歌免费版app&#xff0c;出自乐擎网络的创意工坊&#xff0c;专为孩子们雕琢了一系列富含创意的动画儿歌内容。这款app通过贝乐虎兄弟的可爱形象&#xff0c;让孩子们在愉快的观看中接触到各种儿歌和故事。不仅如此&#xff0c;app还巧妙地将古诗、英语等学习…

Bytebase 2.15.0 - GitOps 整体升级

&#x1f514; GitOps 整体升级 新版 GitOps 和之前版本不兼容&#xff0c;如果需要升级协助&#xff0c;请联系我们。 使用访问令牌进行身份验证。支持项目中配置多个 VCS 连接器。支持在 VCS 连接器中指定数据库分组为目标&#xff08;默认情况下应用于项目中的所有数据库&…

Python | Leetcode Python题解之第25题K个一组翻转链表

题目&#xff1a; 题解&#xff1a; class Solution:# 翻转一个子链表&#xff0c;并且返回新的头与尾def reverse(self, head: ListNode, tail: ListNode):prev tail.nextp headwhile prev ! tail:nex p.nextp.next prevprev pp nexreturn tail, headdef reverseKGroup…

【教学类-52-03】20240412动物数独(4宫格)难度1-9 打印版

作品展示&#xff1a;合并打印&#xff08;难度10%-90%&#xff0c;一共9份&#xff09; 背景需求 前期两个代码完成了4宫格基本样式的制作 【教学类-52-01】20240411动物数独&#xff08;4宫格&#xff09;宫格图https://mp.csdn.net/mp_blog/creation/editor/137679361【教学…

CSS-浮动文字环绕布局、隐藏属性display、overflow、三角形制作、鼠标样式

文字环绕布局 CSS文字环绕布局是指在网页中让文字环绕在图片或其他元素周围的布局方式。这通常通过CSS中的float属性来实现。你可以将图片设置为float: left;或float: right;&#xff0c;然后在文本元素中使用clear属性来清除浮动&#xff0c;以确保文字不会覆盖图片。另外&am…

引领未来:杭州2024快递物流展共绘创新浪潮,塑造智慧物流新蓝图

杭州&#xff0c;作为中国的电商之都&#xff0c;近年来在快递物流行业背景与应用方面取得了显著的发展。随着电子商务的迅猛增长&#xff0c;杭州的快递物流行业迅速崛起&#xff0c;成为支撑电商产业发展的重要力量。 2024长三角&#xff08;杭州&#xff09;快递物流供应链与…

FFmpeg: 简易ijkplayer播放器实现--05ijkplayer–连接UI界面和ffplay.c

文章目录 ijkplayer时序图消息循环--回调函数实现播放器播放时状态转换播放停止 ijkmediaPlay成员变量成员函数 ijkplayer时序图 stream_open: frame_queue_init packet_queue_init init_clock 创建read_thread线程 创建video_refresh_thread线程 消息循环–回调函数实现 ui …

从吉客云到MySQL通过接口配置打通数据

从吉客云到MySQL通过接口配置打通数据 数据源系统:吉客云 吉客云是基于“网店管家”十五年电商ERP行业和技术积累基础上顺应产业发展需求&#xff0c;重新定位、全新设计推出的换代产品&#xff0c;从业务数字化和组织数字化两个方向出发&#xff0c;以构建流程的闭环为依归&am…

大数据入门之如何利用Phoenix访问Hbase

在大数据的世界里&#xff0c;HBase和Phoenix可谓是一对黄金搭档。HBase以其高效的列式存储和强大的数据扩展能力&#xff0c;成为大数据存储领域的佼佼者&#xff1b;而Phoenix则以其SQL化的操作方式&#xff0c;简化了对HBase的访问过程。今天&#xff0c;就让我们一起看看如…

Pandas部分应掌握的重要知识点

目录 Pandas部分应掌握的重要知识点一、DataFrame数据框的创建1、直接基于二维数据创建&#xff08;同时使用index和columns参数&#xff09;2、基于excel文件中的数据来创建 二、查看数据框中的数据和联机帮助信息1、查看特殊行的数据2、查看联机帮助的两种常见方法&#xff0…