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;其系统架构的设计和实施至关重要。本文将深入探讨物联网平台系统架构的关键要素和最佳实…

题目:利用ellipse and rectangle 画图。

题目&#xff1a;利用ellipse and rectangle 画图。 There is no nutrition in the blog content. After reading it, you will not only suffer from malnutrition, but also impotence. The blog content is all parallel goods. Those who are worried about being cheated …

ARM CoreLink 系列的互连产品包括哪些?

ARM CoreLink 系列的互连产品包括多种不同的技术&#xff0c;旨在为系统级芯片&#xff08;SoC&#xff09;提供高性能、高效率和高可靠性的互连解决方案。以下是一些主要的 CoreLink 互连产品&#xff1a; CoreLink CCN (Cache Coherent Network) 系列 CoreLink CCN-504: 这是…

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

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

链表中倒数最后k个结点【c语言】

#include <stdio.h> #include <stdlib.h>typedef struct Node {int data;struct Node* next; } Node, *LinkedList;// 创建一个新节点 Node* createNode(int data) {Node* newNode (Node*)malloc(sizeof(Node));if (newNode NULL) {printf("Error! Unable t…

P4119 [Ynoi2018] 未来日记

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

word并排比较

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

灯光1-灯光与阴影的关系

灯光与阴影之间存在密切的关系。在计算机图形学和视觉效果中&#xff0c;灯光是用来模拟现实世界中的光照情况的一种技术。通过设置不同的灯光属性和位置&#xff0c;可以产生各种不同的光照效果&#xff0c;其中之一就是阴影。 当一个物体被照亮时&#xff0c;光线会被物体表…

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

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

国内代理IP对网络安全的影响及其应对策略

国内代理IP对网络安全的影响主要体现在以下几个方面&#xff1a; 1. 隐私保护&#xff1a; - 使用国内代理IP可以隐藏用户的真实IP地址&#xff0c;增加网络匿名性。这有助于防止第三方追踪用户的在线活动&#xff0c;减少个人信息泄露的风险&#xff0c;特别是对于敏感操作或访…

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;还可能制约企业的长远发展。以下是一些主要的人才队伍建设瓶颈&#xff1a; 首先&#xff0c;专业技术人才短缺是一个突出问题。火力发电行业…

SpringBoot中的yaml 与properties文件书写格式

本文参考https://c.biancheng.net/spring_boot/example.html SpringBoot starter Spring Boot 将日常企业应用研发中的各种场景都抽取出来&#xff0c;做成一个个的 starter&#xff08;启动器&#xff09;&#xff0c;starter 中整合了该场景下各种可能用到的依赖&#xff…

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

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

算法与数据结构 顺序栈(C++)

随机产生10个100以内的整数建立一个顺序栈&#xff0c;从栈顶到栈底依次显示栈内元素&#xff1b;从键盘输入出栈元素个数 n (1< n <10)&#xff0c;将 n 个元素依次出栈并显示出栈元素&#xff0c;再显示此时栈顶元素。 #include <iostream> #include <cstd…

电源——BUCK详解

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

mysql 大表凌晨定时删除数据

有几张表数据量非常大&#xff0c;一次维护量有点大&#xff08;一个月有500多万条数据&#xff0c;并且还在往上涨&#xff09;&#xff0c; 于是想了个定时删除数据&#xff0c;每天凌晨执行&#xff0c;这样每天删除数据量就小&#xff0c; 循环删除&#xff0c;每次删除5…

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还巧妙地将古诗、英语等学习…