Initializer List

红色
绿色
蓝色

Initializer List

An initializer list forces so-called value initialization, which means that even local variables of fundamental types, which usually have an undefined initial value, are initialized by zero(or nullptr, if it is a pointer).

int i;              //i has undefined value
int j{};            //j is initialized by 0
int *p;             //p has undefined value
int *q{};           //q is initialized by nullptr

Note, however, that narrowing initializations----those that reduce precision or where the value gets modified ---- are not possible with braces. For example:

int x1(5.3);                            //OK, but x1 becomes 5
int x2 = 5.3                            //OK, but x2 becomes 5
int x3{5.0};                            //error:narrowing
int x4 = {5.3};               //error:narrowing; [warning] narrowing on gcc
char c1{7};            //Ok. even though 7 is an int, this is not narrowing
char c2{99999};        //error:narrowing (99999 does't fit into a char)
std::vector<int> v1 {1, 2, 3, 4};       //OK
std::vector<int> v2 {1, 2.3, 4, 5.6};   //error:narrowing

initializer_list<>

To support the concept of initializer lists for user-defined types, C++11 provides the class template std::initializer_list<>. It can be used to support initialization by a list of values or in any other place where you want to process just a list of value. For example:

void print(std::initializer_list<int> vals){
    for(auto p = vals.begin(); p != vals.end(); p++){
        std::cout << *p << "\n";
    }
}       // 传给 initializer_list 的东西一定必须也是个 initializer list 或是一个 a list of values
print({12, 2, 3, 4, 5}); //pass a list of value to print()

When there are constructors for both a specific number of arguments and an initializer list, the version with the initialier list is preferred. For example:

class P{
public:
    P(int a, int b){
        cout << "P(int, int), a=" << a << ", b=" << b << endl;
    }

    P(std::initializer_list<int> initlist){
        cout << "P(initializer_list<int>), values=";
        for(auto i : initlist){
            cout << i << endl;
        }
        cout << endl;
    }
};

P p(77, 5);         //P(int, int), a=77, b=5
P q{77, 5};         //P(initializer_list<int>), values= 77 5
P r{77,5,42};       //P(initializer_list<int>), values= 77 5 42
P s={77,5};         //P(initializer_list<int>), values= 77 5

Without the constructor for the initializer list, the constructor taking two ints would be called to initialize q and s, while the initialization of r would be invalid.

initializer_list source code


    1. constexper 关键字:const并未区分出编译期常量和运行期常量, constexpr限定在了编译期常量。
    1. noexcept 关键字:该关键字告诉编译器,函数中不会发生异常,这有利于编译器对程序做更多的优化。如果在运行时,noexecpt函数向外抛出了异常(如果函数内部捕捉了异常并完成处理,这种情况不算抛出异常),程序会直接终止,调用std::terminate()函数,该函数内部会调用std::abort()终止程序。

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.
    constexper initializer_list(const_iterator __a, size_type __l)
        : _M_array(__a), _M_len(__l) { }

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

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

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

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

新版本的 min、max 用到了 initializer_list

cout << max({ 54, 16, 48, 5 }); //54
cout << min({ 54, 16, 48, 5 }); //5
cout << max({ string("Ace", string("Stacy"), string("Barkley"))}); //Ace
cout << min({ string("Ace", string("Stacy"), string("Barkley"))}); //Stacy


template<typename _Tp>
inline _Tp
max(std::initializer_list<_Tp> __l){
    return *std::max_element(__l.begin(), __l.end());
}

template<typename _Tp>
inline _Tp
min(std::initializer_list<_Tp> __l){
    return *std::min_element(__l.begin(), __l.end());
}
posted @ 2020-11-19 16:17  Codroc  阅读(170)  评论(0编辑  收藏  举报