在CPP11之前的不同对象都有各自的初始化方式,于是初始化列表特性的目的在于统一初始化环节
统一初始化
提供了基本类型、数组、自定义类型等不同对象的初始化
class Student
{
public:
Student(string name, int age)
: m_name(name), m_age(age) {
cout << __FUNCTION__ << endl;
}
private:
string m_name;
int m_age;
};
Student s1("Jeson", 18); // 传统方式
Student s2{ "Mark", 18 }; // 初始化列表
int a1 {10};
int a2 = {10};
int * arr = new int[4]{ 0, 2, 4, 5 };
注意事项:自定义类型是尽量实现对应的构造函数,虽然初始化列表支持使用默认构造按照声明顺序进行初始化,但是从开发规范的角度来说,这种方式容易产生隐藏bug,不易排查
struct Student
{
string m_name;
int m_age;
};
Student s1{ "Jeson", 18 }; // 编译通过; s1.m_name == Jeson ; s1.m_age == 18
Student s2{ 18, "Jeson" }; // 编译不通过
类型安全
初始化列表可以防止"缩窄"的隐式类型转换,对于小到大的则不做限制
int a1 = 3.14; // 编译通过
int a2 = {3.14}; // 编译不过,vs2017报错(error C2397: 从“double”转换到“int”需要收缩转换)
double b1 = 3; // 编译通过
double b2 = {3}; // 编译通过
初始化模板类-std::initializer_list
cpp11提供了std::initializer_list
模板类,可将其作为构造函数的参数,如果类有接受initializer_list作为参数的构造函数,则初始化列表语法就只能用于该构造函数。
class A
{
public:
A(std::initializer_list<int> list) {
cout << "A(std::initializer_list<int> list)" << endl;
}
A(int a, int b) {
cout << "A(int a, int b)" << endl;
}
};
A a1{ 1, 2 }; // A(std::initializer_list<int> list)
A a2(1, 2); // A(int a, int b)
参考
- 《C++ Primer Plus(第6版)中文版》