C++11 花括号/大括号的初始化
序言
别问我为什么都是标记简析,深入分析我还没那个精力,为什么写这个这么简单的文章?在某次与群友探讨时才发现自己对于{}的理解是错的,我原来以为{}的使用并没有使用其本身的构造函数,所以特记录铭记。
聚合初始化
在以下条件下,即无任何可用的,用户自己写的,或继承来的构造函数,所有成员变量均是公有的,且非静态
- 没有私有或者受保护非静态数据成员
- 没有用户声明的构造函数
- 没有用户提供的构造函数(允许显式预置或弃置的构造函数)
- 没有用户提供、继承或 explicit 构造函数(允许显式预置或弃置的构造函数)
- 没有用户声明或者继承的构造函数
- 没有虚、私有或受保护 (C++17 起)基类
- 没有虚拟成员函数
- 无默认成员初始化器(C++11 起)(C++14 前)
例子:
struct Test
{
bool a = true;
int b = 4;
std::string c;
};
Test t{false, 5, "str"};
其初始化是要注重于顺序的。
有构造的{}初始化
普通类
普通有自己声明的构造函数,其 {} 初始化 和()无区别,若无对应的构造函数则无法初始化,有对应的构造函数则是直接调用其构造函数。
class Test
{
public:
Test(const int& a, const int& b) :
_a(a), _b(b)
{}
private:
int _a;
int _b;
};
Test t(5, 10); //与下一样无区别
Test e{5, 10}; //与上一样无区别
Test s(4); //编译错误:no matching constructor for initialization of 'Test'
Test d{4}; //编译错误:no matching constructor for initialization of 'Test'
使用initializer_list的类
如果该类是使用std::initializer_list作为构造的形参,{}就又有所不一样了
```cpp
class Test
{
public:
Test(const int& a, const int& b) : //设是T1构造
{}
Teed(std::initializer_list< int > ins) //设是T2构造
{}
Teed(const int& a, const std::string& c) //设是T3构造
{}
private:
...
};
Test q(5, 10); //运行T1
Test w{5, 10}; //运行T2
Test e(5, "10"); //运行T3
Test r{5, "10"}; //运行T3
Test t(4); //编译错误:no matching constructor for initialization of 'Test'
Test y{4}; //运行T2
当用std::initializer_list作为构造的形参时,如果{}的初始化内容是刚好符合的,则会优先使用T2构造而非T1构造
但如果是不符合的,但就会使用符合其参数顺序的构造函数T3构造。
注:T1,T2,T3仅是个代号,无任何实际含义和非专业名称