c++新特性之初始化列表

c++新特性之初始化列表

initializer Lists

用途:

用来设置初值

int i; //undefined 
int j{} // 0
int *p;//uhdefined
int *q{} //nullptr

需要注意的 narrowing initializations

当有数据丢失的风险时会报错 或者 warining 下面是在gcc7.5.0上测试的结果

int x1(5.3);//OK 
int x2 = 5.3;//OK
int x3{5.3}; //error: narrowing conversion of ‘5.2999999999999998e+0’ from ‘double’ to ‘int’ inside { } [-Wnarrowing]
int x4 = {5.3}; // error: narrowing conversion of ‘5.2999999999999998e+0’ from ‘double’ to ‘int’ inside { } [-Wnarrowing]
char c1 {7}; //OK
char c2{257}; //error: narrowing conversion of ‘257’ from ‘int’ to ‘char’ inside { } [-Wnarrowing]
std::vector<int> v1 {1,2,3,4,5};//OK
std::vector<int> v2{1,2.3,4,4.6};/ error: narrowing conversion of ‘2.2999999999999998e+0’ from ‘double’ to ‘int’ inside { } [-Wnarrowing]

c++11 提供了initializer_list<> 类来支撑上面的用法,我们也可以自己使用这个类,例如:

//tips
//标准库中的容器都有initializer_list为参赛的构造函数,故下面的
//initializer_list可以改为 deque,vector,list 
auto print = [](std::initializer_list<int> vals) 
{
    for(auto p = vals.begin();p!=vals.end();++p)
    {
        std::cout<<*p<<std::endl;       
    }
};

print({1,2,3,4,5,6,7,13});

参数匹配规则:

  1. 如果有参数为initializer_list的函数,直接会调用对应参数为initializer_list的函数
  2. 如果没有参数为initializer_list的函数,则进行拆分initializer_list,去匹配有相同参数个数,相同参数类型的函数。
class P
{
public:
    // fun1
    P(int a, int b)
    {
        std::cout<< "P(int,int)"<<std::endl;
    }
    //fun2
    P(std::initializer_list<int> initlist)
    {
        std::cout<<"P(initializer)"<<std::endl;
    }
};
// fun1 与 fun2 同时存在的调用结果
P p(77, 5); // P(int,int)
P q{77, 5}; //P(initializer)
P r{77, 55, 26}; //P(initializer)
P s = {77, 5};   //P(initializer)

// 去掉构造函数fun2 只保留fun1
P p(77, 5); // P(int,int)
P q{77, 5}; //P(int,int)
P r{77, 55, 26}; //error: no matching function for call to ‘P::P(<brace-enclosed initializer list>)’
P s = {77, 5};   //P(int,int)

initializer_list 的实现原理

以下代码摘自 gcc 7.5.0

initializer_list的构造函数为 private故我们不能主动调用它,看注释可知这个构造函数是编译器可调用的。

故:当我们 使用大括号时 如{12,3,4,5},编译器会先生成一个数组,然后用数字的首地址,和size来构造initializer_list。

Tips

  1. const_iterator类型为const _E* 也就是元素的指针,它指向的是array的地址,故array 到initializer_list应该是浅拷贝。
  2. 标准库中用了大量的initializer_list,如容器的构造,插入,还有算法如:max({string(“abc”,string(“c”),string(“defg”)}),min({1,2,5,4,6,7,8})
//以下代码摘自 gcc 7.5.0 #include<initializer_list>
template<class _E>
class initializer_list
{
public:
    typedef _E 		value_type;
    typedef const _E& 	reference;
    typedef const _E& 	const_reference;
    typedef size_t 		size_type;
    typedef const _E* 	iterator;
    typedef const _E* 	const_iterator;

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) { }

public:
    constexpr initializer_list() noexcept
    : _M_array(0), _M_len(0) { }

    // Number of elements.
    constexpr size_type
    size() const noexcept { return _M_len; }

    // First element.
    constexpr const_iterator
    begin() const noexcept { return _M_array; }

    // One past the last element.
    constexpr const_iterator
    end() const noexcept { return begin() + size(); }
};

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值