CPP11-初始化列表


在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 list) {
        cout << "A(std::initializer_list list)" << endl;
    }
    A(int a, int b) {
        cout << "A(int a, int b)" << endl;
    }
};

A a1{ 1, 2 };    // A(std::initializer_list list)
A a2(1, 2);      // A(int a, int b)

参考

  • 《C++ Primer Plus(第6版)中文版》