初始化列表

考虑如下代码:

vector<double> v = { 1, 2, 3.456, 99.99 };
list<pair<string,string>> languages = {
    {"Nygaard","Simula"}, {"Richards","BCPL"}, {"Ritchie","C"}
};
map<vector<string>,vector<int>> years = {
    { {"Maurice","Vincent", "Wilkes"},
              {1913, 1945, 1951, 1967, 2000} },
    { {"Martin", "Ritchards"},
              {1982, 2003, 2007} },
    { {"David", "John", "Wheeler"},
              {1927, 1947, 1951, 2004} }
};

现在,初始化列表不再仅限于数组。可以接受一个“{}列表”对变量进行初始化的机制实际上是通过一个可以接受参数类型为std::initializer_list的函数(通常为构造函数)来实现的。例如:

void f(initializer_list<int>);
f({1,2});
f({23,345,4567,56789});
f({});  // 以空列表为参数调用f()
f{1,2}; // 错误:缺少函数调用符号( )
years.insert({{"Bjarne","Stroustrup"},{1950, 1975, 1985}});

初始化列表可以是任意长度,但必须是同质的(所有的元素必须属于某一模板类型T, 或可转化至T类型的)。

容器可以用如下方式来实现“初始化列表构造函数”:

template<class E> class vector {
public:
    // 初始化列表构造函数
            vector (std::initializer_list<E> s)
    {
           // 预留出合适的容量
              reserve(s.size());    //
        // 初始化所有元素
            uninitialized_copy(s.begin(), s.end(), elem);
     sz = s.size(); // 设置容器的size
    }
    // ... 其他部分保持不变 ...
};

使用“{}初始化”时,直接构造与拷贝构造之间仍有细微差异,但不再像以前那样明显。例如,std::vector拥有一个参数类型为int的显式构造函数及一个带有初始化列表的构造函数:

vector<double> v1(7); // OK: v1有7个元素<br />
v1 = 9;         // Err: 无法将int转换为vector
vector<double> v2 = 9;    // Err: 无法将int转换为vector

void f(const vector<double>&);
f(9);               // Err: 无法将int转换为vector

vector<double> v1{7};     // OK: v1有一个元素,其值为7.0
v1 = {9};           // OK: v1有一个元素,其值为9.0
vector<double> v2 = {9};  // OK: v2有一个元素,其值为9.0
f({9});  // OK: f函数将以列表{9}为参数被调用

vector<vector<double>> vs = {
    vector<double>(10), // OK, 显式构造(10个元素,都是默认值0.0)
    vector<double>{10}, // OK:显式构造(1个元素,值为10.0)
        10          // Err :vector的构造函数是显式的
};

函数可以将initializer_list作为一个不可变的序列进行读取。例如:

void f(initializer_list<int> args)
{
    for (auto p=args.begin(); p!=args.end(); ++p)
        cout << *p << "\n";
}

仅具有一个std::initializer_list的单参数构造函数被称为初始化列表构造函数。

标准库容器,string类型及正则表达式均具有初始化列表构造函数,以及(初始化列表)赋值函数等。初始化列表亦可作为一种“序列”以供“序列化for语句”使用。(译注:参见“序列for循环语句”章节)

初始化列表同时也是“统一初始化”方案的一部分。(译注:参见“统一初始化的语法和语义”章节)

参考:

(翻译:dabaitu)