可以用列表初始化。
早在 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 的构造函数和赋值运算符,以自动列表初始化:
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 的构造函数。
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 变量,看下一句,估计没人看得懂:
注意:
auto d = {1.23}; // d 即是 std::initializer_list<double>
auto d = double{1.23}; // 善哉 -- d 即为 double, 并非 std::initializer_list.