【C++11】{}初始化、std::initializer_list、decltype、STL新增容器

这篇具有很好参考价值的文章主要介绍了【C++11】{}初始化、std::initializer_list、decltype、STL新增容器。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1. C++11简介

在2003年C++标准委员会曾经提交了一份技术勘误表(简称TC1),使得C++03这个名字取代了C++98称为C++11之前的最新C++标准名称。
不过由于C++03(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能更好地用于系统开发和库开发、语法更加泛化和简单化、更加稳定和安全,不仅功能更强大,而且能提升程序员的开发效率,公司实际项目开发中也用得比较多,所以我们要作为一个重点去学习。
【C++11】{}初始化、std::initializer_list、decltype、STL新增容器,C++入门到起飞,c++,list,C++11

C++11增加的语法特性非常篇幅非常多,我们这里没办法一 一讲解,所以最近的几篇文章主要讲解实际中比较实用的语法

官方文档

小故事:

1998年是C++标准委员会成立的第一年,本来计划以后每5年视实际需要更新一次标准,C++国际标准委员会在研究C++ 03的下一个版本的时候,一开始计划是2007年发布,所以最初这个标准叫C++ 07。但是到06年的时候,官方觉得2007年肯定完不成C++ 07,而且官方觉得2008年可能也完不成。最后干脆叫C++ 0x。x的意思是不知道到底能在07还是08还是09年完成。
结果2010年的时候也没完成,最后在2011年终于完成了C++标准。所以最终定名为C++11。

2. 统一的列表初始化

首先声明一下:

这个列表初始化和我们类和对象那里学的初始化列表不是一个概念,是不同的。

2.1 {}初始化

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

【C++11】{}初始化、std::initializer_list、decltype、STL新增容器,C++入门到起飞,c++,list,C++11

那我们C语言里面其实就是这样搞的嘛,所以可以认为C++支持这样就是因为要兼容C嘛

那么在C++11中:

C++11扩大了用大括号括起的列表的使用范围,使其可用于所有的内置类型和用户自定义的类型,使用初始化列表时,可添加等号(=),也可不添加。

🆗,我们来演示一下:

【C++11】{}初始化、std::initializer_list、decltype、STL新增容器,C++入门到起飞,c++,list,C++11
大家看,C++11支持我们这样使用{}初始化,并且赋值=也可以省略

然后要注意:

【C++11】{}初始化、std::initializer_list、decltype、STL新增容器,C++入门到起飞,c++,list,C++11
这样写是咋回事?
🆗,这是不是可以认为是调int的默认构造啊,我们之前说过,有了模板之后,内置类型也需要有构造函数了。

然后:

C++11中列表初始化也可以适用于new表达式中
【C++11】{}初始化、std::initializer_list、decltype、STL新增容器,C++入门到起飞,c++,list,C++11

另外:

创建对象时也可以使用列表初始化方式调用构造函数初始化

比如我们之前写过的日期类:

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;
	}
private:
	int _year;
	int _month;
	int _day;
};

【C++11】{}初始化、std::initializer_list、decltype、STL新增容器,C++入门到起飞,c++,list,C++11

2.2 std::initializer_list

那除了上面的场景呢,C++11还支持了STL里面的容器也可以这样去初始化

比如:

【C++11】{}初始化、std::initializer_list、decltype、STL新增容器,C++入门到起飞,c++,list,C++11
🆗,都是可以的,其它容器也可以,大家可以自己试。

那大家思考一下,在容器这里它是如何支持可以这样写的呢?

首先我们来看一下这个:

【C++11】{}初始化、std::initializer_list、decltype、STL新增容器,C++入门到起飞,c++,list,C++11
这里我们直接给一个大括号,里面放一些元素,这是个啥啊。
之前我们初始化数组可以这样写嘛,那它在这里也是一个数组吗?
那数组怎么直接赋值给一个vector呢?
🆗,那不清楚的话我们可以打印看一下它的类型是什么:
【C++11】{}初始化、std::initializer_list、decltype、STL新增容器,C++入门到起飞,c++,list,C++11
大家看,它的类型是一个叫做initializer_list<int>的东西。

那为什么这个东西可以赋值给vector呢?

【C++11】{}初始化、std::initializer_list、decltype、STL新增容器,C++入门到起飞,c++,list,C++11
🆗,大家看红色圈出来的部分,C++11给STL中的这些容器增加了这样一个构造函数。
支持用initializer_list类型的对象去构造vector这些容器。
所以正常使用这个构造应该是这样写:
【C++11】{}初始化、std::initializer_list、decltype、STL新增容器,C++入门到起飞,c++,list,C++11
那我们写成这样
【C++11】{}初始化、std::initializer_list、decltype、STL新增容器,C++入门到起飞,c++,list,C++11
当然也可以,因为构造函数支持隐式类型转换嘛。

那initializer_list这个类是个啥呢?

【C++11】{}初始化、std::initializer_list、decltype、STL新增容器,C++入门到起飞,c++,list,C++11
initializer_list是C++11引入的一种特殊类型,用于简化初始化列表的使用。它可以在构造函数或函数参数中以列表的形式传递一组值。
可以认为它就是一个常量数组,存储在常量区,initializer_list对象中的元素永远是常量值,我们无法改变initializer_list对象中元素的值。
【C++11】{}初始化、std::initializer_list、decltype、STL新增容器,C++入门到起飞,c++,list,C++11
这是它的一些接口

那我们接下来做一件事情:

我们之前不是模拟实现过STL里面的各种容器的,那以vector为例,我们来对它改造一下,让它也支持用initializer_list进行{}初始化和赋值。

怎么做呢?给它增加这个构造函数就行了

【C++11】{}初始化、std::initializer_list、decltype、STL新增容器,C++入门到起飞,c++,list,C++11
🆗,每增加之前我们自己的vector肯定是不行的,而且大家看这个报错,编译器自动就把后面的常量数组识别成initializer list类型了
我们来写一下:
【C++11】{}初始化、std::initializer_list、decltype、STL新增容器,C++入门到起飞,c++,list,C++11
这下我们再来运行
【C++11】{}初始化、std::initializer_list、decltype、STL新增容器,C++入门到起飞,c++,list,C++11
就可以了
然后再提一下就是
【C++11】{}初始化、std::initializer_list、decltype、STL新增容器,C++入门到起飞,c++,list,C++11
如果这里用迭代器遍历的话前面加一个typename,这个我们之前也提过,就是类模板里面直接取内嵌类型它会分不清是类型还是静态成员变量。

当然不止vector可以,我们说了C++11给STL这几个容器都增加了initializer_list版本的构造:

【C++11】{}初始化、std::initializer_list、decltype、STL新增容器,C++入门到起飞,c++,list,C++11
【C++11】{}初始化、std::initializer_list、decltype、STL新增容器,C++入门到起飞,c++,list,C++11

当然除了构造还支持了initializer_list版本的赋值重载:

【C++11】{}初始化、std::initializer_list、decltype、STL新增容器,C++入门到起飞,c++,list,C++11
【C++11】{}初始化、std::initializer_list、decltype、STL新增容器,C++入门到起飞,c++,list,C++11

3. 声明

c++11提供了多种简化声明的方式

3.1 auto

那auto呢我们在C++专栏第一篇文章C++入门的时候就介绍过了,所以这里就不再重复了

3.2 decltype

再来学一个C++11引入的关键字——decltype

什么作用呢?

decltype是可以获取表达式或变量类型的关键字
我们之前用过typeid(变量/表达式).name()可以获取变量或表达式的类型,然后我们可以打印出来查看,而使用decltype我们可以获取类型并使用这个类型

比如:

【C++11】{}初始化、std::initializer_list、decltype、STL新增容器,C++入门到起飞,c++,list,C++11

但是大家可能会说:

【C++11】{}初始化、std::initializer_list、decltype、STL新增容器,C++入门到起飞,c++,list,C++11
上面的场景用auto也是可以的啊。

确实,但是有的场景auto就不行,比如:

我们要定义一个vector,要求vector里面存储的数据类型跟表达式x*y的返回类型一致
【C++11】{}初始化、std::initializer_list、decltype、STL新增容器,C++入门到起飞,c++,list,C++11
大家看,这个场景auto就不行了吧

4. nullptr

这个我们之前也介绍过了

5. 范围for循环

也介绍过了

6. 智能指针

关于智能指针我们后面会单独作为一个章节来给大家讲解

7. C++11STL中的一些变化

下面我们来分析一下C++11中STL与之前相比有了那些变化

首先它增加了一些新容器:

【C++11】{}初始化、std::initializer_list、decltype、STL新增容器,C++入门到起飞,c++,list,C++11
用橘色圈起来是C++11中的一些几个新容器,我们也都介绍过了,但是实际最有用的是unordered_map和unordered_set,另外两个就显得非常鸡肋
【C++11】{}初始化、std::initializer_list、decltype、STL新增容器,C++入门到起飞,c++,list,C++11

其次呢就是增加了一些新方法:

比如提供了cbegin和cend方法返回const迭代器等等,但是实际意义不大,因为begin和end也是可以返回const迭代器的,这些都是属于锦上添花的操作。
实际上C++11更新后,容器中增加的新方法最实用的就是插入接口函数的右值引用版本
【C++11】{}初始化、std::initializer_list、decltype、STL新增容器,C++入门到起飞,c++,list,C++11
【C++11】{}初始化、std::initializer_list、decltype、STL新增容器,C++入门到起飞,c++,list,C++11

那关于这里3、4两点提到的右值引用和移动语义我们后面也会花大量篇幅给大家讲解…

8. 演示代码

把上面演示过的代码给大家:

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;

//struct Point
//{
//	int _x;
//	int _y;
//};
//
//int main()
//{
//	int a(4);
//
//	int b = { 2 };
//	int c{ 3 };
//
//	int arr[]{ 1,2,3,4,5 };
//
//	Point p{ 1,2 };
//
//	// C++11中列表初始化也可以适用于new表达式中
//	int* pa = new int{ 5 };
//	cout << *pa << endl;
//	return 0;
//}

//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;
//	}
//private:
//	int _year;
//	int _month;
//	int _day;
//};
//int main()
//{
//	Date d1(2022, 1, 1); // old style
//
//	// C++11支持的列表初始化,这里会调用构造函数初始化
//	Date d2 = { 2022, 1, 2 };
//	Date d3{ 2022, 1, 3 };
//	return 0;
//}

#include <vector>
#include <list>
//int main()
//{
//	vector<int> v = { 1,2,3,4 };
//
//	vector<int> v2({ 1,2,3,4 });
//
//	list<int> lt = { 2,4,6,8,9 };
//
//	initializer_list<int> il = { 1,2,3,4,5,6,7,8 };
//
//	vector<int> v3 = il;
//
//	return 0;
//}

int main()
{
	const int x = 1;
	double y = 2.2;
	//decltype(x * y) ret; // ret的类型是double
	//decltype(&x) p;		// p的类型是const int*

	auto ret = x * y;
	auto p = &x;

	vector<decltype(x* y)> v;

	cout << typeid(ret).name() << endl;
	cout << typeid(p).name() << endl;

	return 0;
}

【C++11】{}初始化、std::initializer_list、decltype、STL新增容器,C++入门到起飞,c++,list,C++11文章来源地址https://www.toymoban.com/news/detail-731706.html

到了这里,关于【C++11】{}初始化、std::initializer_list、decltype、STL新增容器的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【MySQL安装问题】mysqld --initialize初始化报错

    在显示安装成功MySQL后,初始化mysqld --initialize报错,错误显示如下 2023-04-03T709:05:28.842980Z O[Warning] TMESTAMP with implicit DEFAULT walue is deprecated.Please use -explicit_lefatlts_for_timestamp server option (see documentation for more details). 2023-04-03T09:05:28.8430327O [Warning] \\\'NO_ZERO_DATE\\\', ‘NO_ZBRO _TN DATE\\\' and \\\'ER

    2024年02月11日
    浏览(61)
  • PLSQL启动报错:Initialization error,不能初始化

    出现场景:我这里原来有个旧版的PLSQL,想用新版的又装了个新版,启动的时候报错 第一个提示明显看到是和程序位数相关的,不管是32位还是64位要做到向匹配 第二个提示可以看到是和oci.dll文件的设置相关 登录的时候先点取消,不使用用户登录,进入客户端 检查PLSQL的OC

    2024年01月23日
    浏览(44)
  • ORB-SLAM2算法12之单目初始化Initializer

    ORB-SLAM2算法7详细了解了 System 主类和多线程、

    2024年02月10日
    浏览(32)
  • 从C语言到C++_33(C++11_上)initializer_list+右值引用+完美转发+移动构造/赋值

    目录 1. 列表初始化initializer_list 2. 前面提到的一些知识点 2.1 小语法 2.2 STL中的一些变化 3. 右值和右值引用 3.1 右值和右值引用概念 3.2 右值引用类型的左值属性 3.3 左值引用与右值引用比较 3.4 右值引用的使用场景 3.4.1 左值引用的功能和短板 3.4.2 移动构造 3.4.3 移动赋值

    2024年02月12日
    浏览(23)
  • 【重磅】:Spring Initializer 已经不支持Java8,也就是SpringBoot2.x项目初始化

    我们可以看到在IDEA内置的Spring Initializer中 Java版本选择模块已经不支持1.8了,同样的,官网也不再支持了 Spring Boot 3.x要求 Java最低版本为17, 最新的SpringBoot版本已经要求Java21了 所以,你可以升级Java版本,使用SpringBoot3.X 我们可以尝试查看一下, 访问Spring官网,按照下图操作

    2024年02月04日
    浏览(35)
  • k8s初始化报错[kubelet-check] Initial timeout of 40s passed.

    使用kubeadm进行k8s部署,在初始化的时候,遇到如下 一直卡在了[kubelet-check] Initial timeout of 40s passed.,查看kubelet日志 就出现这个错误,我几个node的IP地址检查过好多遍也没问题 上网找了很多方法都解决不了 查了下资料k8s 已经弃用了docker了,如果安装的kubelet kubeadm kubectl 是V

    2024年02月17日
    浏览(31)
  • PLSQL连接远端Oracle服务器提示:“Initialization error ***不能初始化 oci.dl ***”的解决方案

    【PLSQL连接远端Oracle服务器提示:“Initialization error ***不能初始化 oci.dl ***”的解决方案】 继上篇如题报错提示如何解决事项: 1、其一、确认Oracle服务端、客户端、PLSQL Developer都必须位数一致,32bit/64bit,如出现位数不一致则无法加载。Oracle Instant Client 下载官网 2、其二、配

    2024年02月15日
    浏览(26)
  • Android 11属性系统初始化流程

    在init进程启动的第二阶段,调用PropertyInit 对属性系统进行初始化 PropertyInit函数在systemcoreinitproperty_service.cpp 中实现 注释1处在dev下创建__properties__文件夹。注释2处会收集读取各个分区下的property_contexts文件,将读取到的信息系列化之后,写到/dev/ properties /property_info文件中。

    2024年04月09日
    浏览(43)
  • 【C++11】:统一的列表初始化|声明|STL变化

    ​                                                 🎬慕斯主页 : 修仙—别有洞天                                               ♈️ 今日夜电波:マイノリティ脈絡—ずっと真夜中でいいのに。                                          

    2024年03月26日
    浏览(34)
  • Android 11 Ethernet以太网架构分析(1)——初始化

    android中以太网常被用作共享网络,或者是定制化设备连接网线的需求。 本章将会详细分析该模块对以太网的逻辑实现,是大家对此有更深入认识。 初始化 Systemserver 在安卓系统中有一个关于以太网的服务,在systemserver中启动 frameworks/base/services/java/com/android/server/SystemServer.j

    2024年02月04日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包