我是靠谱客的博主 纯情钥匙,最近开发中收集的这篇文章主要介绍C++20:列表初始化,聚合初始化,强制省略拷贝优化,指定初始化......何为初始化C++98C++11C++17C++20总结,觉得挺不错的,现在分享给大家,希望可以做个参考。
概述
何为初始化
变量的类型决定变量所占用的内存大小和布局;变量在创建是获得一个特定的值,我说这个变量被初始化了。
分类及标准
变量的初始化是C++标准的一个重要组成部分,C++初始化按照是否存在拷贝,可将初始化划分为直接初始化和拷贝初始化;其他初始化均可以归类为此两大类。
C++标准中规定,如果变量使用赋值运算符(=)初始化就是拷贝初始化,否则就是直接初始化。
C++标准
按照C++标准引入时间,笔者将变量初始化相关标准汇总如下:
- C++98标准的直接初始化,拷贝初始化,聚合初始化,圆括号初始化
- C++11标准的列表初始化和initializer_list;
- C++17标准的强制省略拷贝优化,列表初始化类型推导,聚合初始化扩展(允许基类)
- C++20标准的聚合初始化的扩展,指定初始化器初始化。
C++98
C++98标准是C++语言的第一个major版本;此标准引入的初始化包括直接初始化,拷贝初始化,圆括号初始化,花括号以及聚合初始化。
按照前述初始化标准,圆括号初始化属于直接初始化,聚合初始化是一种特殊的拷贝初始化。
直接初始化
未通过拷贝构造实现的初始化就是直接初始化 ,此初始化方式一般通过直接调用构造函数初始化变量。例如:
string s(5,'c'); // s被初始化为"ccccc"
拷贝初始化
拷贝初始化是相对于直接初始化而言的,拷贝初始化通过调用类型的拷贝构造实现对象初始化。例如:
string name = "liuguang";
在C++98标准中,name赋值基于隐式转换经历了2个步骤:
- 调用string入参为const char*构造函数,产生临时string变量temp;
- 执行赋值操作调用入参为temp的string拷贝构造函数,完成name的初始化。
但可惜的是因为编译器优化,我们调试看到却是直接调用构造函数初始化,name初始化会直接调用string入参为const char*构造函数。
所以name初始化本应属于拷贝初始化的,但是优化后会被别人误解为直接初始化。GCC的-fno-elide-constructors和MSVC的/Od可以关闭此编译器优化。
圆括号初始化
圆括号初始化使用()来初始化变量,其是基于使用形式的命名方式,例如:
double d(1.3); // d被初始化为1.3
string s(5,'c'); // s被初始化为"ccccc"
聚合初始化
聚合初始化一般适用于下述两种初始化场景:
- 数组初始化
char a[3] = {'a', 'b', '