C++11新特性(语法糖,新容器)

news2024/11/20 22:40:22

距离C++11版本发布已经过去那么多年了,为什么还称为新特性呢?因为笔者前面探讨的内容,除了auto,范围for这些常用的,基本上是用着C++98的内容,虽说C++11已经发布很多年,却是目前被使用最广泛的版本。因为新版本的发布,编译器要很长时间才能支持新语法新特性,有一句话说得挺好,C/C++之所以强大,是因为它们的编译器很强大。C++23版本已经发布,但真想普遍使用不知道还得多少年呢?尤其是C/C++这种基本用于底层架构的语言,底层代码不敢改,也不愿意改。但不管怎么说,日后的开发是离不开C++11的,C++11可以说是C++历年来最大的版本更新,多了很多非常强大的东西,但也多了很多鸡肋,内容太多太多,不可能全部提完。故而笔者着重讲述必须要掌握的,用处一般的就简单提提,剩下的,大家碰到了再查,C++11新特性部分将分为多篇内容,让我们开始吧

目录

array & forward_list

auto,typeid,decltype

范围for

统一的列表初始化

统一的列表初始化原理 

nullptr 


array & forward_list

C++11新更新了两个容器,分别是array,forward_list

array本质上是对C语言的数组进行了一层封装,加上了模板,迭代器等功能

array的定义如上,它也是一个静态数组,声明时需要指定类型和大小,整体使用下来并不比C语言的数组强多少,唯一比C语言数组好用的就是会检查下标,我们知道C语言的数组越界读是不会报错的,越界写也仅是抽查,所以不小心写错下标可能会造成一些问题

但是vector也能检查下标呀,我为何不使用vector呢,况且vector功能比array强大多了,所以array算是C++11里比较鸡肋的一个

forward_list是新推出的单链表,在C++推出STL库时,只有list,list的底层实现我们前面也探讨过了,本质是双链表。forward_list算是list的青春版,因为双链表的节点要链接前后,所以会比单链表多存储一个指针大小,如果在内存空间特别紧凑,并且单链表足够满足使用场景,可以考虑使用forward_list,其基础功能如下,只能头插和尾插

auto,typeid,decltype

auto,typeid,decltype都是C++11推出的和类型相关的特性功能

auto是语法糖,为什么叫语法糖,因为让人用的舒服,auto是很好用的,在一些场景下,有的类型被层层封装,导致其类型名很长,有了auto就不用我们自己去推断类型

这仅是auto应用场景之一,后面我们会见到大量使用auto的场景,例如范围for就是使用auto来推导要迭代的类型,auto是根据初始值来进行类型推导的,也就是说你要使用auto推导必须给出一个初始值,否则没有意义

auto test;
//没有初始值,无意义的推导

如果你想把某个变量或者表达式的类型给打印出来看看,那么就可以使用typeid,具体用法如下图,typeid是一个类,把想知道类型的变量或者表达式传过去,调用name

调用name之后,会返回一个字符串,字符串的内容即是推导出的类型

如果现在提一个过分一点的要求,我不仅要你推导出类型,还要用你推导的结果再声明出同类型的对象,使用typeid是做不到了,因为它返回的是字符串,不可能作为类型声明符,但是decltype可以做到,看看decltype是如何使用的

上图用decltype推导出test_1的类型,并用推导结果声明了变量test_2

这里的应用场景看着比较傻,类型推导在模板里应用比较广泛,如下

按照常规方法是不好解决的,因为我们不明确 T1 和 T2的类型到底是什么,就没有办法给变量ret_val确定类型,但是现在我们有了auto 和 decltype就很容易解决这个问题

范围for

范围for也是C++11中使用体验不错的语法糖,范围for本质就是循环遍历对象,范围for的出现帮我们节省了不少时间,如下列程序 

不仅内置类型可以用,容器也是可以使用范围for的,如下图程序 

只要容器支持迭代器,那么它就可以使用范围for,因为容器使用范围for本质还是在调用容器中实现的迭代器 ,但是范围for使用起来方便不少,使用汇编可以一窥细节

//测试代码
int main()
{
	vector<int> test;
	for (int i = 1; i <= 10; i++)
	{
		test.push_back(i);
	}

	//迭代器
	auto it = test.begin();
	while (it != test.end())
	{
		cout << *it << " ";
		it++;
	}

	cout << endl;

	//范围for
	for (auto& t : test)
	{
		cout << t << " ";
	}

	return 0;
}

可以看出两者都是在调用迭代器,我们手动调用的begin()和end()是经过封装过的,范围for则直接调用迭代器的底层实现,在容器中范围for本质和迭代器没区别,但是用的更省心 

使用范围for时,如果auto推导类型后跟上&,就是引用调用,可以读写原数据

如果没有跟上&,那么就是传值调用,修改并不会影响原数据

如果只想读不想写的话推荐 const auto & 这种写法,减少拷贝消耗

统一的列表初始化

平时我们给C语言的数组进行初始化操作时,可以使用一对花括号进行赋值" { } "

//使用花括号给数组进行初始化赋值
int arr[] = {1, 2, 3, 4, 5, 6};

其实这样的初始化还挺好用的,我们平时使用vector进行赋值时就没那么方便,如果赋值有顺序还好,没顺序的话还要自己手动push_back,于是C++11提出了统一初始化列表,也就是说让STL中的容器也够支持使用" { } "来进行赋值,如下图

可不仅仅是只有vector能使用,其它容器也是支持的,如下图的list和map

你甚至可以直接不写赋值符号 "=" ,同样能完成初始化,不仅可以用于数组,容器,对于单个内置类型也是可以使用{}来初始化的,如下图 

除了内置类类型和STL库中的容器支持这种初始化,自定义类型也是支持的 

需要注意的是,使用{}初始化自定义类型,是去调用自定义类型的构造函数,由此看来,C++11之后确实可以统一使用{ }来初始化,这也是为什么叫统一的列表初始化

统一的列表初始化原理 

像数组可以使用{}进行初始化可以理解,毕竟原生的编译器就支持,但是容器也支持{}初始化是怎么做到的呢? 其实实现原理也不难,我们以vector为例,既然是初始化,那我们就紧盯构造函数,打开资料库查查C++11的构造函数有没有发生变化

果然,我们发现,构造函数中多了一个initializer list,而这就是统一列表初始化实现的秘密,可以看出该构造函数使用的是initializer_list,我们查一下这是个什么东西

我们大概能理解,使用{ }时,会将里面的内容放到initializer_list容器中存放起来,然后把该容器内的值拷贝给vector,如此就完成了初始化操作,知道原理了,我们可以自己尝试给之前写的vector也添加这么个功能

vector(std::initializer_list<T> _lt)
{
	_begin = new T[_lt.size()];
	_finish = _begin + _lt.size();
	_end = _begin + _lt.size();

	auto _vtp = _begin;
	auto _ltp = _lt.begin();
	while (_ltp != _lt.end())
	{
		*_vtp = *_ltp;
		_vtp++;
		_ltp++;
	}
}

这个只能构造,若想拷贝赋值的话,可以重载一个operator=( std::initializer_list<T> _lt)

具体定义如下,别忘了包含头文件initializer_list

vector<T>& operator=(std::initializer_list<T> _lt)
{
	vector<T> tmp(_lt);
	std::swap(_start, tmp._start);
	std::swap(_finish, tmp._finish);
	std::swap(_endofstorage, tmp._endofstorage);
	return *this;
}

nullptr 

出现nullptr是因为C++错误的将库中的NULL定义为0,这就会导致很多问题,因为NULL不仅表示一个空指针,还是一个字面常量值0,如下述代码

简单写个代码验证其中的危害性

int main()
{
	int p = NULL;
	cout << p << endl;
	int t = 0;
	if (t == NULL) cout << "t是一个空指针" << endl;
	
	return 0;
}

运行结果如上,t被错误的判断为一个空指针,事实上,t连指针都不是错已经错了,直接改NULL会影响原先的代码,为了解决这个问题,C++又推出了nullptr来代替NULL 

nullptr则是正确的定义 (void*)0,所以C++中请使用nullptr来表示空指针

至此,本篇文章就结束了,总体下来还算轻松,很多内容都是见过多次的老朋友了,其中也多了不少好用的特性,像统一初始化列表,范围for这种就快快用起来吧

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

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

相关文章

string类的模拟实现(万字讲解超详细)

目录 前言 1.命名空间的使用 2.string的成员变量 3.构造函数 4.析构函数 5.拷贝构造 5.1 swap交换函数的实现 6.赋值运算符重载 7.迭代器部分 8.数据容量控制 8.1 size和capacity 8.2 empty 9.数据修改部分 9.1 push_back 9.2 append添加字符串 9.3 运算符重载…

Nacos与Eureka的区别

大家好我是苏麟今天说一说Nacos与Eureka的区别. Nacos Nacos的服务实例分为两种l类型&#xff1a; 临时实例&#xff1a;如果实例宕机超过一定时间&#xff0c;会从服务列表剔除&#xff0c;默认的类型。非临时实例&#xff1a;如果实例宕机&#xff0c;不会从服务列表剔除&…

Python安装指南:安装Python、配置Python环境(附安装包)

1. 选择正确的版本&#xff0c;下载安装包 根据你的实际需要选择Python发行版本。 值得注意的是&#xff0c;编程语言包并不是越新越好的&#xff0c;不同版本的Python之间可能会产生兼容性问题。 如果你不确定你的项目需要哪个版本&#xff0c;请查阅您可能需要使用到的插件的…

输入电压转化为电流性 5~20mA方案

输入电压转化为电流性 5~20mA方案 方案一方案二方案三 方案一 XTR111是一款精密的电压-电流转换器是最广泛应用之一。原因有二&#xff1a;一是线性度非常好、二是价格便宜。总结成一点&#xff0c;就是性价比高。 典型电路 最终电路 Z1二极管处输出电流表达式&#xff1a;…

(c语言进阶)数据存储——浮点型存储

一.常见的浮点数 二.浮点数存储规则 1.float存储规定 2.double存储规定 3.M的存储规则 4.E的存储规则 5.指数E从内存中取出的三种情况 &#xff08;1&#xff09;E不全为0或不全为1 &#xff08;2&#xff09;E全为0 &#xff08;3&#xff09;E全为1 三.举例 1.经典…

【高级rabbitmq】

文章目录 1. 消息丢失问题1.1 发送者消息丢失1.2 MQ消息丢失1.3 消费者消息丢失1.3.1 消费失败重试机制 总结 2. 死信交换机2.1 TTL 3. 惰性队列3.1 总结&#xff1a; 4. MQ集群 消息队列在使用过程中&#xff0c;面临着很多实际问题需要思考&#xff1a; 1. 消息丢失问题 1.1…

Multi Label Classification with Missing Labels(MLML)的几种loss设计

多标签学习这个方向问题比较多&#xff0c;可以参考多标签学习的新趋势&#xff08;2021 Survey TPAMI&#xff09; 和 部分标签学习和缺失标签学习到底什么异同&#xff1f; 这两篇偏综述性质的解释。本文重点解释下面几个重点问题&#xff1a; Multi Label Classification w…

山西电力市场日前价格预测【2023-10-06】

日前价格预测 预测说明&#xff1a; 如上图所示&#xff0c;预测明日&#xff08;2023-10-06&#xff09;山西电力市场全天平均日前电价为425.53元/MWh。其中&#xff0c;最高日前电价为777.87元/MWh&#xff0c;预计出现在18: 45。最低日前电价为328.89元/MWh&#xff0c;预计…

ICCV 2023 获奖论文公布,扩散模型、分割一切、跟踪一切摘得桂冠

昨天计算机视觉三大顶级会议之一的ICCV 2023在法国巴黎正式“开奖”了&#xff01;今年共有两篇论文获得最佳论文奖&#xff0c;大名鼎鼎的“分割一切”荣获最佳论文提名。 ICCV今年共收录了2160篇论文&#xff0c;从今年的录用论文的主题领域来看&#xff0c;3D视觉、图像视频…

大促节奏:速卖通黑五接力双十一,如何打造产品权重瓜分活动流量

双十一和黑五作为一种独特的消费文化现象&#xff0c;已经逐渐成为了消费领域中的一块“金字招牌”。无论是消费者还是商家&#xff0c;都非常期待这一天的到来&#xff0c;因为它不仅代表着购物的欲望和刺激&#xff0c;更重要的是&#xff0c;双十一和黑五已经成为了一种全新…

在springboot项目中整合Druid

或 1.导入maven坐标 <dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.2.19</version> </dependency>2.在application.properties中配置连接池 spring:datasource:d…

微信管理系统

在这个全民微信的时代&#xff0c;微信已成为生活和工作中不可缺少的工具&#xff0c;为了方便&#xff0c;大部分人都不会只有一个微信&#xff0c;很多企业老板和创业者都已经开始用微信管理系统来提升自身的业务效率和客户满意度。 微信管理系统适用哪些行业呢&#xff1f; …

SSM - Springboot - MyBatis-Plus 全栈体系(二十)

第四章 SpringMVC 二、SpringMVC 接收数据 3. 接收 Cookie 数据 可以使用 CookieValue 注释将 HTTP Cookie 的值绑定到控制器中的方法参数。 考虑使用以下 cookie 的请求&#xff1a; JSESSIONID415A4AC178C59DACE0B2C9CA727CDD84下面的示例演示如何获取 cookie 值&#x…

小谈设计模式(19)—备忘录模式

小谈设计模式&#xff08;19&#xff09;—备忘录模式 专栏介绍专栏地址专栏介绍 备忘录模式主要角色发起人&#xff08;Originator&#xff09;备忘录&#xff08;Memento&#xff09;管理者&#xff08;Caretaker&#xff09; 应用场景结构实现步骤Java程序实现首先&#xff…

如何使用 Media.io 生成不同年龄的照片

Media.io 是一个在线图片编辑器&#xff0c;提供多种功能&#xff0c;包括照片滤镜、图像裁剪和图像转换。其中&#xff0c;Media.io 的 AI 年龄转换功能可以根据上传的照片&#xff0c;生成不同年龄的照片。 使用 Media.io 生成不同年龄的照片 要使用 Media.io 生成不同年龄…

微信朋友圈还可以这么玩?

微信“朋友圈”除了日常了解好友动态外&#xff0c;就是时不时分享下自己的生活日常&#xff01; 但你知道吗&#xff0c;其实朋友圈还有许多有趣的玩法&#xff0c;只可惜只有“少数人”知晓&#xff01;一起来看看吧 01 关闭个性化“朋友圈”广告 微信作为我们生活的社交圈&…

try catch无法获取空指针异常的长度的问题

项目代码里有对异常进行捕获&#xff0c;然后根据异常的长度决定是否截取异常内容保存数据库的操作&#xff0c;然后对于空指针的异常是无法获取异常的长度的。 这个是获取空指针异常长度。 然后现在不获取异常的长度 解决方法&#xff1a;

Vue3 模糊搜索筛选

Vue3 模糊搜索筛选 环境&#xff1a; vue3 tselement plus 目标&#xff1a; 输入框输入内容&#xff0c;对展示的列表进行模糊搜索筛选匹配的内容。 代码如下&#xff1a; <div style"margin-top: 50px"><el-input v-model"valueInput" size&…

C++笔记之信号量、互斥量与PV操作

C笔记之信号量、互斥量与PV操作 文章目录 C笔记之信号量、互斥量与PV操作1.信号量概念2.信号量例程一3.信号量例程二4.信号量例程三5.互斥量6.PV操作概念7.PV操作详解——抄自&#xff1a;https://mp.weixin.qq.com/s/vvjhbzsWQNRkU7-b_dURlQ 1.信号量概念 C中的信号量是一种同…

【牛客网-面试必刷TOP 101】01链表

BM1 反转链表 解题思路 第一种方法&#xff1a;借助栈 1. 栈的特点是先进后出&#xff0c;用stack来存储链表&#xff0c;之后新建一个头节点&#xff0c;按出栈顺序拼接形成新的链表。 2. 注意&#xff0c;最后一个节点的next要赋值null 3. 空间复杂度O(N), 时间复杂度O(N)J…