列表初始化的特性来源于单参数的隐式类型转换。以下面这个赋值为例,我们可以理解成
- 先创建一个匿名对象Point(2),这个时候就变成了 Point p = Point(2);
- 然后会调用拷贝构造。
虽然隐式转换的可以这样理解,但是最后会被编译器优化成直接调用有参构造(下面自定义类型列表初始化模块会证明)。
Point p = 2;        // Point是一个自定义类
                    // Point p = Point(2); 
                    // 最后会被编译器优化成: Point p(2);列表初始化的基本原理和上面类似,只不过是由单参数的隐式类型转换变成了多参数的隐式类型转换。
目录
1、内置类型的列表初始化
(1) 数组
(2) 动态数组
(3) 标准容器
2、自定义类型的列表初始化
1、内置类型的列表初始化
(1) 数组
在C++11以后,即便没有等号也可以初始化。
int arr1[5] = {1,2,3,4,5};       // int arr2[5]{1,2,3,4,5};
int arr2[] = {1,2,3,4,5};        // int arr2[]{1,2,3,4,5};
(2) 动态数组
动态数组也可以使用{ } 来做到列表初始化。这是C++11以后支持的新特性,C++98不支持。
int* arr3 = new int[5]{1,2,3,4,5};(3) 标准容器
容器使用列表初始化时,本质是将初始化列表转换成了 initializer_list 类型,然后再调用构造函数 vector(initializer_list<T> il) 来进行初始化 。
vector<int> v{1,2,3,4,5};    // 本质是调用了构造函数vector(initializer_list<T> il) 
map<int, int> m{{1,1}, {2,2,},{3,3},{4,4}};vector(initializer_list<T> il)的模拟实现大体如下,其中initializer_lis支持使用迭代器访问初始化列表
vector(initializer_list<T> il)
{
    // 判断是否需要扩容
    // 使用迭代器遍历初始化列表,逐个插入到数组中
    initializer_list<T>::iterator it = il.begin();
    while(it != il.end())
    {
        push_back(*it);
        it++;
    }
}
2、自定义类型的列表初始化
假设有这样一个自定义类型 Point:
class Point
{
public:
     Point(int x = 0, int y = 0): _x(x), _y(y)
     {
        cout << "Point(int x, int y) 被调用了" << endl;
     }
private:
     int _x;
     int _y;
};我们可以一次给该类的多个成员进行初始化,前提是该类包含对应的有参构造函数。和最开始的理解方式一致,可以理解成先创建一个匿名对象,然后调用拷贝构造。实际上会被编译器优化成直接调用有参构造。
int main()
{
    Point p = {1, 2};    // Point p(1, 2);
}
注意:如果要禁止这样的隐式类型转换(列表初始化),可以使用explicit关键字
![[Android]Bitmap Drawable](https://img-blog.csdnimg.cn/accc337971af4ee3839114832f7bffe6.jpeg)








![数据结构课程设计[2023-01-19]](https://img-blog.csdnimg.cn/img_convert/e66a4e1d29ded6e6c23aa8c03ad65876.png)






![[数据结构基础]链式二叉树的几个典型的基础oj问题](https://img-blog.csdnimg.cn/32cd4510e13843459bed1a38b86aba8a.png)


