一.默认初始化
调用无参或者时提供了默认参数的构造函数。
二.拷贝初始化
A a;
A b = a;
A c = 3; // 默认class A有一个形参为int的构造函数。先将3隐式转换为A,然后调用复制构造函数。
三.直接初始化
我的理解:使用非复制构造且提供初始值作为构造函数实参的初始化。
四.列表初始化
①
int a{0}, b = {0}; // 正确
double a = 3.14;
int c = {a}, d{a}; // 错误,存在信息丢失的风险,C++Primer原话。用g++测试发现只是给出一个警告,而在聚合类初始化时,发生类型丢失根本没有错误且没有警告
//原因:只有常量在编译时期才会被<span style="color:#FF0000;">评估求值</span>,所以声明a为constexpr变量时,编译才是出错。注意,const也不行。
int c = {3.14}; // g++测试编译出错,同样适用于聚合类。
②单个对象的初始化
如:聚合类(所有成员都是public、没有定义任何构造函数、没有类内初始值、没有基类也没有virtual函数):关系到C++对象模型。
class/struct A
{
public:
int a;
int b;
int c;
};
A get()
{
return {1,2,3};
}
③数组或者模板形式的多个元素的初始化
如:vector
vector<int> ivec = {0,1,2,3,4};
vector<string> svec = {“asa”, “qqw”, “rtert”};
vector<string> svec = {10}; // 10个默认初始化的元素
vector<string> svec2 = {10, “asda”}; //10个值为“asda”的元素
④在构造函数冒号后面的初始化也属于列表初始化
应当注意,在构造函数里初始化和列表初始化在效率方面有所区别,详细参考《深度探索C++对象模型》。
五.值初始化
如:
①在初始化数组时,提供的初始值数少于数组长度,剩余的提供默认初始化。
②不使用初始值定义局部静态变量。
③在vector模板中之提供元素个数不提供初始值,则元素进行的默认初始化也叫值初始化。
int *p = new int();
string *ps = new string();
int *p = new int; // default constructor
对于定义了自己的默认构造函数的类,要求值初始化是没意义的,它最终都是通过默认构造函数来初始化;对于内置类型,值初始化有着良好定义的值,而默认初始化的对象的值是未定义的。
所以,在涉及类的情况,类必须提供默认构造函数以便上述情况发生。
六.类内初始值
如:
class A
{
const int a = 3;
static constexpr double b = 10.0;
};