6.20. 列表初始化
Tip
你可以用列表初始化。
早在 C++03 里,聚合类型(aggregate types)就已经可以被列表初始化了,比如数组和不自带构造函数的结构体:
- struct Point { int x; int y; };
- Point p = {1, 2};
C++11 中,该特性得到进一步的推广,任何对象类型都可以被列表初始化。示范如下:
- // Vector 接收了一个初始化列表。
- vector<string> v{"foo", "bar"};
- // 不考虑细节上的微妙差别,大致上相同。
- // 您可以任选其一。
- vector<string> v = {"foo", "bar"};
- // 可以配合 new 一起用。
- auto p = new vector<string>{"foo", "bar"};
- // map 接收了一些 pair, 列表初始化大显神威。
- map<int, string> m = {{1, "one"}, {2, "2"}};
- // 初始化列表也可以用在返回类型上的隐式转换。
- vector<int> test_function() { return {1, 2, 3}; }
- // 初始化列表可迭代。
- for (int i : {-1, -2, -3}) {}
- // 在函数调用里用列表初始化。
- void TestFunction2(vector<int> v) {}
- TestFunction2({1, 2, 3});
用户自定义类型也可以定义接收 std::initializer_list<T>
的构造函数和赋值运算符,以自动列表初始化:
- class MyType {
- public:
- // std::initializer_list 专门接收 init 列表。
- // 得以值传递。
- MyType(std::initializer_list<int> init_list) {
- for (int i : init_list) append(i);
- }
- MyType& operator=(std::initializer_list<int> init_list) {
- clear();
- for (int i : init_list) append(i);
- }
- };
- MyType m{2, 3, 5, 7};
最后,列表初始化也适用于常规数据类型的构造,哪怕没有接收 std::initializer_list<T>
的构造函数。
- double d{1.23};
- // MyOtherType 没有 std::initializer_list 构造函数,
- // 直接上接收常规类型的构造函数。
- class MyOtherType {
- public:
- explicit MyOtherType(string);
- MyOtherType(int, string);
- };
- MyOtherType m = {1, "b"};
- // 不过如果构造函数是显式的(explict),您就不能用 `= {}` 了。
- MyOtherType m{"b"};
千万别直接列表初始化 auto 变量,看下一句,估计没人看得懂:
Warning
- auto d = {1.23}; // d 即是 std::initializer_list<double>
- auto d = double{1.23}; // 善哉 -- d 即为 double, 并非 std::initializer_list.
至于格式化,参见 9.7. 列表初始化格式.