统一初始化(Uniform Initialization)

原文:C++值初始化,默认初始化,以及其他初始化类型的区别?
     C++11 带来的新特性(2)-统一初始化(Uniform Initialization)
在C++11之前,初始化没有一个统一的写法,对象的初始化方式是不同的(小括号,大括号,赋值),C++11努力创造一个统一的初始化方式,其语法是使用{}std::initializer_list。我们调用的一般形式是:

[new] T [object] {arg1, arg2, ...};

list initialization & aggregate initialization

从简单情况来说,list initialization我们并不陌生,本质上就是:

  • 如果T是aggregate类型,list中的参数对object成员逐个初始化,若list参数个数小于T成员个数,剩余成员调用value initialization
  • 如果T不是aggregate类型,编译器查找最匹配list参数的T的构造函数。

通过一个例子看看具体细节:

std::vector<int> v{1, 2, 3};
  • 首先,参数列表{1, 2, 3}转换为std::initializer_list
    从stl的源码中可以看出initializer_list带参数的构造函数是一个私有函数,只能通过编译器调用。
    private:
      iterator          _M_array;
      size_type         _M_len;

      // The compiler can call a private constructor.
      constexpr initializer_list(const_iterator __a, size_type __l)
      : _M_array(__a), _M_len(__l) { }
  • 其次,使用std::initializer对象来初始化std::vector的构造函数。
      vector(initializer_list<value_type> __l,
         const allocator_type& __a = allocator_type())
      : _Base(__a)
      {
    _M_range_initialize(__l.begin(), __l.end(),
                random_access_iterator_tag());
      }

value initialization

如果在list initialization行驶中,没有任何参数args,也就是:

[new] T [object] {};

值初始化一般有三种处理方式:

  • 如果T有用户定义的缺省构造函数,直接调用;
  • 如果T有编译器生成的缺省构造函数,先0值初始化再调用;
  • 如果T根本不是类,直接0值初始化。

default initialization

[new] T [object];

缺省初始化除了在值初始化过程中可能进行之外,也可以以上面形式单独进行。这种初始化的独特地方在于,如果T是非class类型,则给出非确定值(不赋值),比如:

    int i;      //i值未定义
    int j{};    //j=0
    int *p;     //p值未定义
    int *q{};   //q=nullptr

zero initialization

0值初始化除了在值初始化过程中可能进行之外,也可以单独作用于静态(或者线程局部)变量:

static T object;

总结

理解的要点在于,list中的参数要么按构造函数的参数声明顺序,要么按aggregate类型成员声明顺序,逐个赋值。当某些成员没有被这样显示给定值时,进行广义缺省初始化(value initialization):或调用缺省构造函数,或赋0值。

posted @ 2020-10-30 10:57  cbhxutt  阅读(487)  评论(0编辑  收藏  举报