【c++11】新的类功能和可变参数包

news2024/12/23 12:04:25

c++11

  • 新增默认成员函数
    • 类成员变量初始化
    • 关键字
    • default
      • delete
    • 委托构造
  • 可变参数包
    • 递归展开参数包
    • 逗号表达式展开参数包
  • 结语

新增默认成员函数

原来c++类中,有6个默认成员函数:

  1. 构造函数
  2. 析构函数
  3. 拷贝构造函数
  4. 拷贝赋值重载
  5. 取地址函数
  6. const 取地址重载

默认成员函数就是我们不写编译器会生成一个默认的。

c++11后又新增两个

  1. 移动构造函数
  2. 移动运算符重载

对于新增的这两个,但其默认生成的条件比较苛刻:

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

为什么移动构造函数生成的条件那么严苛呢?
因为对于一个类,如果实现了析构,拷贝构造等函数,说明了这个类需要进行深拷贝,最好是自己对这个类的资源进行控制和转移,编译器希望我们自己实现移动构造函数。

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

看如下代码:

class Person
{
public:
	Person(const char* name, int age)
		:_name(name)
		, _age(age)
	{}
	
			/*~Person()
				{}*/
private:
	lx::string _name;
	int _age;
};

int main()
{
	Person s1("张三",18);
	Person s2 = s1;
	Person s3 = move(s1);
	return 0;
}

在这里插入图片描述
可以看到,编译器默认生成的移动函数调用了lx::string 的移动构造函数,所以最后会打印出一个拷贝构造和一个移动构造。

当我们实现一个拷贝构造函数


	Person(const Person& p):_name(p._name)
		,_age(p._age)
		{}
	

那么编译器不会生成移动构造函数,那么会直接调用拷贝构造函数。
在这里插入图片描述
移动赋值重载函数也类似:

如果你没有自己实现移动赋值重载函数,且没有实现析构函数 、拷贝构造、拷贝赋值重载中的任意一个,那么编译器会自动生成一个默认移动赋值。默认生成的移动构造函数,对于内置类型成员会执行逐成员按字节拷贝,自定义类型成员,则需要看这个成员是否实现移动赋值,如果实现了就调用移动赋值,没有实现就调用拷贝赋值。

类成员变量初始化

C++11允许在类定义时给成员变量初始缺省值。

class grades {
private:
	int Math=100;
	int Chinese=100;
	int English=100;
};

关键字

default

强制生成默认函数的关键字default。假设你需要使用某个默认的函数,在某些情况下该函数没有默认生成,比如:我们提供了拷贝构造,就不会生成移动构造了,那么我们可以使用default关键字显示指定移动构造生成。

Person(Person&& p) = default;

delete

禁止生成默认函数的关键字delete。
如果能想要限制某些默认函数的生成,在C++98中,是该函数设置成private,并且只声明函数,这样只要其他人想要调用就会报错。

在C++11中更简单,只需在该函数声明加上=delete即可,该语法指示编译器不生成对应函数的默认版本,称=delete修饰的函数为删除函数。

Person(const Person& p) = delete;

如果再次运行,就会得到这样的报错
在这里插入图片描述
尝试引用已经删除的函数。

委托构造

委托构造,也是一个构造函数,但它不直接对类对象进行赋值,而是委托其它构造函数对类对象进行处理。如:

class Person
{
public:
	Person(const char* name, int age)
		:_name(name)
		, _age(age)
	{}
	//委托构造
	Person(const char* name)
		:Person(name, 18)
	{}
	private:
	lx::string _name;
	int _age;
};

注意:委托构造函数也要于其它构造函数进行区分,否则编译器无法识别。

了解即可,可以不深入了解其运用。等用到的时候在仔细研究一下就行了。

可变参数包

C++11的新特性可变参数模板能够创建可以接受可变数量参数的函数模板和类模板,相比C++98/03,类模版和函数模版中只能含固定数量的模版参数,可变模版参数无疑是一个巨大的改进。

//Args是模板的可变参数包
template <class ...Args>
//args是函数的可变参数包
// 声明一个参数包Args...args,这个参数包中可以包含0到任意个模板参数。
void fun(Args ...args)
{
	cout << sizeof...(args) << endl;
}

上面的参数args前面有省略号,所以它就是一个可变模版参数,我们把带省略号的参数称为“参数包”,它里面包含了0到N(N>=0)个模版参数。

我们无法直接获取参数包args中的每个参数的,只能通过展开参数包的方式来获取参数包中的每个参数。
那么如何获取参数包的每个参数呢?
是这样嘛

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

是不是觉得就是这样的啊,但是
在这里插入图片描述
编译器提示要在上下文扩展参数包,不能用打印数组的方式解析参数包。

递归展开参数包

代码如下:


//终止函数
void fun()
{
	cout << endl;
}

template <class T,class ...Args>
void fun(const T& val,Args ...args)
{
	cout << val << ':';
	cout << sizeof...(args) << endl;//  打印出可变参数包的大小
	fun(args...);
}

int main()
{
  	fun(1,‘a’,std::string("hello wrold"));

	return 0;
}

结果如下
在这里插入图片描述
成功解析出了可变参数包的内容。
那么是如何解析出来的呢?
且听我细细分说:

运用了函数递归的原理

在这里插入图片描述
每次递归的时候将参数包的第一个传递给val,后面的参数形成一个新的参数包,每一次递归,参数包就减少一位i,被打印在屏幕上。

当参数包里的参数为0时,也就不能为下一次递归传递参数,所以编译器会调用
终止函数。调用完了后也会依次回溯。

逗号表达式展开参数包

这种展开参数包的方式,不需要通过递归终止函数,是直接在expand函数体中展开的, print_arg不是一个递归终止函数,只是一个处理参数包中每一个参数的函数。这种就地展开参数包的方式实现的关键是逗号表达式。我们知道逗号表达式会按顺序执行逗号前面的表达式.

template<class T>
void print_arg(const T& t)
{
	cout << t << " ";
}

template <class ...Args>
void  fun(Args... args)
{
	int arr[] = { (print_arg(args),0)... };
	cout << endl;
}

int main()
{
  	fun(1,‘a’,std::string("hello wrold"));

	return 0;
}

也能打印出参数包里的每一个参数。
同样,这是怎么来的呢?
且听我一一道来:
逗号表达式:(printarg(args), 0),先执行printarg(args),再得到逗号表达式的结果0。
同时还用到了C++11的另外一个特性——初始化列表,通过初始化列表来初始化一个变长数组, {(prin_targ(args), 0)…}将会展开成

((print_arg(arg1),0), (print_arg(arg2),0), (print_arg(arg3),0), etc... )

对于我们的函数,在编译阶段,编译器会将其推演生成成这样一段代码,

void fun(int a1, char a2, std::string a3)
{
	int arr[] = { (print_arg(a1),0),(print_arg(a2),0),(print_arg(a3),0) };
	cout << endl;
}

最终会创建一个元素值都为0的数组int arr[sizeof…(Args)]。

由于可变模版参数比较抽象,使用起来需要一定的技巧,所以这块还是比较晦涩的。现阶段呢,我们掌握一些基础的可变参数模板特性就够我们用了,所以这里我们点到为止,以后大家如果有需要,再可以深入学习。

结语

本次的博客就到这了。

我是Tom-猫,
如果觉得有帮助的话,记得
一键三连哦ヾ(≧▽≦*)o。

咱们下期再见。

在这里插入图片描述

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

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

相关文章

将mp4视频推流rtsp,并转为http直播流,在前端显示

最近有个需求&#xff0c;在vue页面的video组件播放直播流&#xff0c;本来想用flv.js&#xff0c;但是必须要flv格式才行&#xff0c;所以还是用原生video播放http直播流。 1. 将本地mp4推流rtsp 下载并解压EasyDarwin&#xff0c;双击EasyDarwin.exe运行&#xff0c;在控制…

【python】web应用开发DRF框架

DRF 【python】web应用开发DRF框架 Django rest_framework, 简称 drf, 可以更方便的使用django写出符合 RESTful 规范的接口, (缩减编写api接口的代码) Django REST framework是一个建立在Django基础之上的Web应用开发框架(Django的一个app)&#xff0c;可以快速的开发REST A…

【IMX6ULL驱动开发学习】12.Linux驱动之设备树

承接上一篇博客 【IMX6ULL驱动开发学习】11.驱动设计之面向对象_分层思想&#xff08;学习设备树过渡部分&#xff09; 代码获取&#xff1a;https://gitee.com/chenshao777/imx6-ull_-drivers 我后面将三个层合并了&#xff08;实际上只有前两层&#xff09;&#xff0c;合并…

【Java入门】注释、关键字、常量、变量、数据类型

注释&#xff1a; 作用 : 可以记录代码所实现的功能&#xff0c;方便程序员或代码编写者阅读代码以及方便他人更好理解代码 注释分类&#xff1a; 单行注释 格式&#xff1a; //注释信息多行注释 格式&#xff1a; /注释信息/文档煮熟 格式&#xff1a;/** 注释信息*/ /***…

TCP的socket API

1、核心类 ServerSocket &#xff1a;服务器使用的socket Socket : 服务器和客户端都会使用的socket accept进行的工作是拉客 对应操作系统来说&#xff0c;建立TCP连接是内核的工作 accept要干的就是等连接建立好了&#xff0c;把这个连接给拿到应用程序中。 如果当前连接…

chatgpt赋能python:Python获取文件后缀名

Python获取文件后缀名 在Python编程中&#xff0c;经常需要获取文件的后缀名&#xff0c;例如在处理文件上传、下载、压缩等操作时&#xff0c;需要对文件后缀名进行判断和处理。本文将介绍Python获取文件后缀名的两种常用方法。 方法一&#xff1a;使用split()函数 Python的…

【C语言初阶(2)】循环语句:while 循环

文章目录 1. while 语句介绍1.1 语法结构1.2 while 语句执行的流程 2. while 语句中的 break 和 continue2.1 break 介绍2.2 continue 介绍 我们已经掌握了 if 语句&#xff0c;当条件满足的情况下&#xff0c;if 语句的后的语句执行&#xff0c;反之不执行&#xff1b; 但是 i…

ChatGPT最新版多功能批量写作工具激发创作的无限可能

随着科技的不断发展&#xff0c;人工智能逐渐渗透到各个领域&#xff0c;其中包括写作领域。近年来&#xff0c;OpenAI推出的ChatGPT最新版多功能批量写作工具&#xff0c;为写作者们带来了全新的创作体验。这一工具不仅能够帮助写作者提高工作效率&#xff0c;还能够激发创作的…

chatgpt赋能python:Python获取定位的SEO指南

Python获取定位的SEO指南 什么是SEO SEO&#xff0c;即搜索引擎优化&#xff0c;是通过对网站进行优化&#xff0c;提高排名&#xff0c;从而增加搜索引擎来的流量&#xff0c;并达到提高转化率的目的。在这个数字时代&#xff0c;对于大多数网站来说&#xff0c;SEO已经成为…

idea maven 中模块显示灰色,依赖不加载

idea maven 中模块显示灰色&#xff0c;依赖刷新了几次都无法加载引入 后面发现是被MAVEN设置忽略了 去掉忽略文件然后reimport &#xff0c;就正常了

通过cifar-10数据集理解numpy数组的高(H)、宽(W)、通道数(C)

文章目录 1、CIFAR-10数据集介绍1.1 CIFAR-10数据集的构成1.2 batches.meta1.3 data_batch_n.py & test_batch.py 2、获取一张图片的data数据2.1 反序列化获得numpy数据2.2 清楚numpy中的H、W、C的含义2.3 清楚RGB图片在numpy中的表示 3、处理图片数据的代码 1、CIFAR-10数…

IDEA启动报错:Process finished with exit code 0

问题 SpringBoot项目启动后自动关闭 方案一 在pom中添加spring-boot-starter-web依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-tomcat</artifactId> </dependency>方案二 在pom中…

CodeTON Round 5 (Div. 1 + Div. 2, Rated, Prizes!) A-D

1842A - Tenzing and Tsondu 题意 丁真和珍珠宝可梦对决, 每个宝可梦都有x战力, 假设有两个宝可梦, 其战力分别为a和b(a>b), 战力为a的宝可梦获胜后战力-b, 而战败的宝可梦会消失 最后还有宝可梦的人获胜 问你丁真和珍珠谁赢了 题解 显而易见, 赢下来的宝可梦可以继续打…

GcWord 6.1.4 Crack -GrapeCity Documents for Word

用于 Microsoft Word 文档的 .NET 6 API 通过代码完全控制您的 Word 文档&#xff0c;而不依赖于 Microsoft Word。 生成、加载、编辑和保存 Word 文档 基于 Microsoft Office API 的功能丰富的对象模型 从头开始或使用生成报告 报告模板 兼容多种平台&#xff0c;例如 Window…

vue-cli2 碎碎念念

vue create 和 vue init webpack 的区别&#xff1a; https://blog.csdn.net/qq_45955152/article/details/123506724 https://blog.csdn.net/qq_22182989/article/details/103611934 区别1&#xff1a; 区别2&#xff1a; 实践&#xff1a;

CadLib 4.0.2023.31601 net for Windows Crack

CadLib 4.0 for Windows&#xff1a;在 C# VB .NET 中读取、写入和显示 AutoCAD DWG 和 DXF 文件 CadLib 4.0 for Windows仅在Windows上运行&#xff0c;并且基于.NET 4.x。 CadLib 4.0读取、写入和显示 C#、VB.NET 或任何其他 .NET 语言的 AutoCAD™ DWG 和 DXF 文件。下载试…

Selenium教程__浏览器窗口大小(6)

本文将介绍如何使用Selenium来获取和设置浏览器窗口的大小&#xff0c;以及一些实际应用场景。 学习本文内容将能够轻松地控制浏览器窗口的大小&#xff0c;从而更好地适应不同的屏幕分辨率和设备&#xff0c;并确保网页在各种窗口大小下都能够良好地展示。 import time fro…

机器学习(二)逻辑回归

Logistic Regression 虽然被称为回归&#xff0c;但其实际上是分类模型&#xff0c;并常用于二分类。 Logistic 回归的本质是&#xff1a;假设数据服从这个分布&#xff0c;然后使用极大似然估计做参数的估计。 逻辑回归API介绍 sklearn.linear_model.LogisticRegression(sol…

配置apache只允许通过域名通过ssl访问

配置好IP&#xff0c;配置好bind解析 Yum安装相关软件包 进入证书目录 先用date –s 设置正确的系统时间。 创建私钥 创建证书 把私钥转换成不需要密码的 把私钥移动到私钥目录 编辑/etc/httpd/conf.d/ssl.conf 设置根目录&#xff0c;主机名。 限制80端口访问。在最后插入 设…

蜘蛛池包收录 - 百度代发排名

蜘蛛池包收录 - 百度代发排名 通话时长越长点击扣费越多吗&#xff1f; 相信这个是很多推 OCPC 用户都关注的问题&#xff0c;因为有时候接了一个电话&#xff0c;跟客户通了十几分钟&#xff0c;挂断之后发现竟然点一下扣了一百多&#xff0c;甚至二百多&#xff0c;这是什么…