红色
绿色
蓝色
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 << "
";
}
} // 传给 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
-
- constexper 关键字:const并未区分出编译期常量和运行期常量, constexpr限定在了编译期常量。
-
- 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());
}