列表初始化(内置类型、自定义类型)

列表初始化的特性来源于单参数的隐式类型转换。以下面这个赋值为例,我们可以理解成

  • 先创建一个匿名对象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关键字

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值