深入了解—C++11特性

目录

一、 C++11简介

二、初始化列表

2.1 C++98中{}的初始化问题

2.2 内置类型的列表初始化

2.3 自定义类型的列表初始化

2.3.1. 标准库支持单个对象的列表初始化

2.3.2. 多个对象的列表初始化

三、变量类型推导

3.1 为什么需要类型推导

3.2 decltype类型推导

3.2.1. 推演表达式类型作为变量的定义类型

​编辑

3.2.2. 推演函数返回值的类型

四、范围for循环

五、final与override

5.1 final

5.2 override

六、默认成员函数控制

6.1 显式缺省函数

6.2删除默认函数

总结


一、 C++11简介

在2003年C++标准委员会曾经提交了一份技术勘误表(简称TC1),使得C++03这个名字已经取代了C++98称为C++11之前的最新C++标准名称。不过由于TC1主要是对C++98标准中的漏洞进行修复,语言的核心部分则没有改动,因此人们习惯性的把两个标准合并称为C++98/03标准。从C++0x到C++11,C++标准10年磨一剑,第二个真正意义上的标准珊珊来迟。相比于C++98/03,C++11则带来了数量可观的变化,其中包含了约140个新特性,以及对C++03标准中约600个缺陷的修正,这使得C++11更像是从C++98/03中孕育出的一种新语言。相比较而言,C++11能更好地用于系统开发和库开发、语法更加泛华和简单化、更加稳定和安全,不仅功能更强大,而且能提升程序员的开发效率

二、初始化列表

2.1 C++98中{}的初始化问题


在C++98中,标准允许使用花括号{}对数组元素进行统一的列表初始值设定。比如:

int array1[] = {1,2,3,4,5};
int array2[5] = {0};

对于一些自定义的类型,却无法使用这样的初始化。比如:

vector<int> v{1,2,3,4,5};

vector就无法通过编译,导致每次定义vector时,都需要先把vector定义出来,然后使用循环对其赋初始值,非常不方便。C++11扩大了用大括号括起的列表(初始化列表)的使用范围,使其可用于所有的内置类型和用户自定义的类型,使用初始化列表时,可添加等号(=),也可不添加。

2.2 内置类型的列表初始化

int main()
{
	// 内置类型变量
	int x1 = { 10 };
	int x2{ 10 };
	int x3 = 1 + 2;
	int x4 = { 1 + 2 };
	int x5{ 1 + 2 };
	// 数组
	int arr1[5]{ 1,2,3,4,5 };
	int arr2[]{ 1,2,3,4,5 };
	// 动态数组,在C++98中不支持
	int* arr3 = new int[5]{ 1,2,3,4,5 };
	// 标准容器
	vector<int> v{ 1,2,3,4,5 };
	map<int, int> m{ {1,1}, {2,2,},{3,3},{4,4} };
	return 0;
}

注意:列表初始化可以在{}之前使用等号,其效果与不使用=没有什么区别。

2.3 自定义类型的列表初始化

2.3.1. 标准库支持单个对象的列表初始化

class Point
{
public:
	Point(int x = 0, int y = 0) : _x(x), _y(y)
	{}
private:
	int _x;
	int _y;
};
int main()
{
	Pointer p{ 1, 2 };
	return 0;
}

2.3.2. 多个对象的列表初始化

多个对象想要支持列表初始化,需给该类(模板类)添加一个带有initializer_list类型参数的构造函数即可。注意:initializer_list是系统自定义的类模板,该类模板中主要有三个方法:begin()、end()迭代器以及获取区间中元素个数的方法size()。

#include <initializer_list>
template<class T>
class Vector {
public:
	// ...
	Vector(initializer_list<T> l) 
		: _capacity(l.size())
		, _size(0)
	{
		_array = new T[_capacity];
		for (auto e : l)
			_array[_size++] = e;
	}
	Vector<T>& operator=(initializer_list<T> l) 
	{
		delete[] _array;
		size_t i = 0;
		for (auto e : l)
			_array[i++] = e;
		return *this;
	}
	// ...
private:
	T* _array;
	size_t _capacity;
	size_t _size;
};

三、变量类型推导

3.1 为什么需要类型推导

在定义变量时,必须先给出变量的实际类型,编译器才允许定义,但有些情况下可能不知道需要实际类型怎么给,或者类型写起来特别复杂,比如:

#include <map>
#include <string>
int main()
{
	short a = 32670;
	short b = 32670;
	// c如果给成short,会造成数据丢失,如果能够让编译器根据a+b的结果推导c的实际类型,就不会存在问题
	short c = a + b;
	std::map<std::string, std::string> m{ {"apple", "苹果"}, {"banana","香蕉"} };
	// 使用迭代器遍历容器, 迭代器类型太繁琐
	std::map<std::string, std::string>::iterator it = m.begin();
	while (it != m.end())
	{
		cout << it->first << " " << it->second << endl;
		++it;
	}
	return 0;
}

C++11中,可以使用auto来根据变量初始化表达式类型推导变量的实际类型,可以给程序的书写提供许多方便。将程序中c与it的类型换成auto,程序可以通过编译,而且更加简洁

3.2 decltype类型推导

auto使用的前提是:必须要对auto声明的类型进行初始化,否则编译器无法推导出auto的实际类型。但有时候可能需要根据表达式运行完成之后结果的类型进行推导,因为编译期间,代码不会运行,此时auto也就无能为力。

如果能用加完之后结果的实际类型作为函数的返回值类型就不会出错,但这需要程序运行完才能知道结果的实际类型,即RTTI(Run-Time Type Identification 运行时类型识别)

C++98中确实已经支持RTTI:

typeid只能查看类型不能用其结果类定义类型
dynamic_cast只能应用于含有虚函数的继承体系中

运行时类型识别的缺陷是降低程序运行的效率。
 

decltype是根据表达式的实际类型推演出定义变量时所用的类型,比如:

3.2.1. 推演表达式类型作为变量的定义类型

int main()
{
	int a = 10;
	int b = 20;
	// 用decltype推演a+b的实际类型,作为定义c的类型
	decltype(a + b) c;
	cout << typeid(c).name() << endl;
	return 0;
}

3.2.2. 推演函数返回值的类型

void* GetMemory(size_t size)
{
	return malloc(size);
}
int main()
{
	// 如果没有带参数,推导函数的类型
	cout << typeid(decltype(GetMemory)).name() << endl;
	// 如果带参数列表,推导的是函数返回值的类型,注意:此处只是推演,不会执行函数
	cout << typeid(decltype(GetMemory(0))).name() << endl;
	return 0;
}

四、范围for循环

范围for是C++11新引入的特性,可遍历各种序列结构的容器(如数组、vector、list等);每次循环都会将序列中的下一个元素,赋值给声明的变量,直到循环结束;

使用条件:

范围for迭代的范围需确定(如下图:数组名为数组首地址,直接从开始打印到结尾)

迭代的对象要实现++和==操作

原理是通过序列的迭代器来遍历其中的元素,编译器会自动处理迭代器的初始化、增量及结束等细节,无需手动操作

注意事项:

1.范围for迭代的范围是确定的,所以无需担心下班越界;
2.可遍历定义了begin() 和 end() 方法的对象,如vector,set,list,map,queue,deque,string;
3.不可使用指针(如new生成的数组)作为循环结构里的序列;
4.由于数组在遍历的时候会转换成指针,所以在遍历多维数组的时候,除最内层循环外,其他所有循环的控制变量都要使用引用的形式。

五、final与override

5.1 final

final修饰类的时候,表示该类不能被继承

final修饰虚函数时,这个虚函数不能被重写

5.2 override

检查派生类虚函数是否重写了基类某个虚函数,如果没有重写编译报错

六、默认成员函数控制

在C++中对于空类编译器会生成一些默认的成员函数,比如:构造函数、拷贝构造函数、运算符重载、析构函数和&和const&的重载、移动构造、移动拷贝构造等函数如果在类中显式定义了,编译器将不会重新生成默认版本。有时候这样的规则可能被忘记,最常见的是声明了带参数的构造函数,必要时则需要定义不带参数的版本以实例化无参的对象。而且有时编译器会生成,有时又不生成,容易造成混乱,于是C++11让程序员可以控制是否需要编译器生成。

6.1 显式缺省函数

在C++11中,可以在默认函数定义或者声明时加上=default,从而显式的指示编译器生成该函数的默认版本,用=default修饰的函数称为显式缺省函数。

class A
{
public:
	A(int a) : _a(a)
	{}
	// 显式缺省构造函数,由编译器生成
	A() = default;
	// 在类中声明,在类外定义时让编译器生成默认赋值运算符重载
	A& operator=(const A& a);
private:
	int _a;
};
A& A::operator=(const A& a) = default;
int main()
{
	A a1(10);
	A a2;
	a2 = a1;
	return 0;
}

6.2删除默认函数

如果能想要限制某些默认函数的生成,在C++98中,是该函数设置成private,并且不给定义,这样只要其他人想要调用就会报错。在C++11中更简单,只需在该函数声明加上=delete即可,该语法指示编译器不生成对应函数的默认版本,称=delete修饰的函数为删除函数。

class A
{
public:
	A(int a) : _a(a)
	{}
	// 禁止编译器生成默认的拷贝构造函数以及赋值运算符重载
	A(const A&) = delete;
	A& operator(const A&) = delete;
private:
	int _a;
};
int main()
{
	A a1(10);
	// 编译失败,因为该类没有拷贝构造函数
	//A a2(a1);
	// 编译失败,因为该类没有赋值运算符重载
	A a3(20);
	a3 = a2;
	return 0;
}

总结

C++11这次带来了大量的更新,使我们敲代码更加的便利,除了以上几个方面,还有几个比较方便的改动会以新的单独的小章节继续分享给大家,主要是   右值引用  lambda表达式 智能指针和线程库。如果本章节帮助到了您,希望您的点赞评论收藏进行支持,我也会继续努力更新新的章节。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

方法-PC端远程调试分布式训练

本专栏为深度学习的一些技巧,方法和实验测试,偏向于实际应用,后续不断更新,感兴趣童鞋可关,方便后续推送 简介 一些简单的代码我们使用Pycharm本地调试就能运行成功&#xff0c;但在诸如使用GPU进行分布式训练和推断等场景中&#xff0c;由于我们本地的电脑没有GPU或者没有多…

慢SQL的治理经验

其他系列文章导航 Java基础合集数据结构与算法合集 设计模式合集 多线程合集 分布式合集 ES合集 文章目录 其他系列文章导航 文章目录 前言 一、慢SQL导致的后果 二、可能导致慢SQL的原因 三、如何发现慢SQL 3.1 JVM Sandbox 四、识别高危SQL 4.1 阿里的重点强制SQL规…

docker容器-compose单机容器编排

yaml文件&#xff1a;是一种标记语言&#xff0c;以竖列的形式展示序列化的数据格式&#xff0c;可读性高 类似于json格式&#xff0c;语法简单 yaml通过缩进来表示数据结构&#xff0c;连续的项目用-减号来表示 yaml文件使用的注意事项 1、大小写敏感 2、通过缩进表示层级…

VUE3语法--toRefs与toRef用法

1、功能概述 ref和reactive能够定义响应式的数据&#xff0c;当我们通过reactive定义了一个对象或者数组数据的时候&#xff0c;如果我们只希望这个对象或者数组中指定的数据响应&#xff0c;其他的不响应。这个时候我们就可以使用toRefs和toRef实现局部数据的响应。 toRefs是…

AntDB数据库致力降本增效的某省高速清分结算实践——优势总结和推广意义

中国正处于数字化转型的关键时期&#xff0c;高速公路正朝着智慧高速的建设迈进。不论是传统的传统高速卡口&#xff0c;诸如“数据采集、数据上传”和“数据处理”的基础建设1.0时代&#xff0c;还是不久将来即将实现的具备“车辆协同智能”、“边缘控制中心”及“智慧高速云控…

vue+element项目中页面多个接口异常,只提示一次异常信息

有时候一个页面会同时调多个接口&#xff0c;但是多个接口异常&#xff0c;需要做提示&#xff0c;那么提示的时候会弹出很多的提示信息&#xff0c;这无疑让体验感降低很多。 所以针对这种情况&#xff0c;我们配合element UI统一做一个异常状态的处理&#xff0c;只能显示一…

MATLAB实现图像变换和滤波

MATLAB实现图像变换和滤波方法对具有不同特征的灰度图像进行处理 图像变换方法包括&#xff1a;DFT及IDFT&#xff0c;DCT及IDCT 图像滤波方法包括低通滤波和高通滤波 图像变换 DFT/IDFT 图像一般是二维的&#xff0c;根据二维离散傅里叶变换公式DFT&#xff0c;可以将图片…

多线程案例-定时器(附完整代码)

定时器是什么 定时器是软件开发中的一个重要组件.类似于一个"闹钟".达到一个设定的时间之后,就执行某个指定好的代码. 定时器是一种实际开发中非常常用的组件. 比如网络通信种,如果对方500ms内没有返回数据,则断开尝试重连. 比如一个Map,希望里面的某个key在3s之后过…

视频播放插件ckplayer

地址&#xff1a;https://www.ckplayer.com/demo.html 效果图

events.out.tfevents文件信息提取

深度学习训练数据有时候是记录在log文件中&#xff0c;文件名类型为events.out.tfevents.xxx.king,当然这些文件可以通过tensorbord工具可视化&#xff0c;这里提供一些events.out.tfevents文件信息提取的方法。 &#xff08;1&#xff09;events.out.tfevents多个文件可视化 …

UniGui使用CSSUniTreeMenu滚动条

有些人反应UniTreeMenu当菜单项目比较多的时候会超出但是没有出滚动条&#xff0c;只需要添加如下CSS 老规矩&#xff0c;unitreemeu的layout的componentcls里添加bbtreemenu&#xff0c;然后在css里添加 .bbtreemenu .x-box-item{ overflow-y: auto; } 然后当内容超出后就会…

反射篇笔记

反射的本质&#xff1a;加载类。 把某个类的字节码文件加载到内存中。并允许以变成的方式解剖类中的各种成分&#xff08;成员方法&#xff0c;变量&#xff0c;构造器&#xff09;。 例如在使用IDEA时&#xff0c;他的提示&#xff0c;就是利用反射&#xff0c;提前将类中的…

AMEYA360:海康存储PCIe4.0固态硬盘A4000介绍

海康存储即将发布PCIe4.0固态硬盘新品A4000&#xff0c;搭载全新定制主控及高品质3D NAND闪存颗粒&#xff0c;最大顺序读取速度达7100MB/s&#xff0c;提供五年质保服务。 2022年&#xff0c;海康存储开始在PCIe 4.0固态硬盘领域全面发力&#xff0c;推出C4000 ECO、C4000等多…

将自己的django项目部署到云服务器(腾讯云centos)

最近自己买了个云服务玩&#xff0c;突然就想把自己写的小项目部署到云服务器上&#xff0c;这样就可以实现公网访问了。以下是整个部署过程和遇到的各种问题的解决方案&#xff0c;有想自己部署自己功能的&#xff0c;可以参考着进行哦。 1、设置好腾讯云的远程登录代码 先给…

yarn历史日志_配置文件

yarn历史日志yarn配置文件yarn执行任务 1.3. YARN的历史日志 1.3.1. 历史日志概述 我们在YARN运行MapReduce的程序的时候&#xff0c;任务会被分发到不同的节点&#xff0c;在不同的Container内去执行。如果一个程序执行结束后&#xff0c;我们想去查看这个程序的运行状态呢…

接口芯片选型分析 四通道差分驱动可满足ANSI TIA/EIA-422-B 和ITU V.11 的要求 低功耗,高速率,高ESD

四通道差分驱动可满足ANSI TIA/EIA-422-B 和ITU V.11 的要求 低功耗&#xff0c;高速率&#xff0c;高ESD。 其中GC26L31S可替代AM26LS31/TI&#xff0c;GC26L32S替代AM26LS32/TI&#xff0c;GC26E31S替代TI的AM26LV31E

19.java绘图

A.Graphics类 Graphics类是java.awt包中的一个类&#xff0c;它用于在图形用户界面&#xff08;GUI&#xff09;或其他图形应用程序中进行绘制。该类通常与Component的paint方法一起使用&#xff0c;以在组件上进行绘制操作。 一些Graphics类的常见用法和方法&#xff1a; 在组…

天软基金经理因子定期报告(2023-12)

天软基金经理因子定期报告&#xff08;2023-12&#xff09;报告概要&#xff1a; 从投资业绩来看&#xff0c;葛兰长期业绩表现优于市场&#xff0c;任职以来年化收益率为12.714%&#xff0c;最大回撤为-53.460%。 从投资能力来看&#xff0c;其选股能力与收益择时能力较为突出…

发布 Whatsonchain 上的 BSV20 插件

我们发布了 whatsonchain 上的 BSV20 插件来验证 BSV20 代币。 对于任何交易&#xff0c;whatsonchain 都可以通过以下网址打开&#xff1a; https://whatsonchain.com/tx/{hash}我们使用此 bsv20 v21 交易 打开 Whatsonchain 。 打开whatsonchain后你会看到BSV20插件&#x…