统一的初始化
C++11扩大了用大括号括起的列表(初始化列表)的适用范围,使其可用于所有内置类型和用户定义的类型。使用初始化列表时,可以添加等号,也可不添加。
int x = {5};
double y {2.75};
short quar[5] {4, 5, 2, 76, 1};
int * ar = new int[4] {2, 4, 6, 7};
/*创建对象时,也可以使用大括号括起的列表来调用构造函数*/
Stump s1(3, 15.6); /*old style*/
Stump s2{5, 43.4}; /*C++11*/
Stump s3 = {4, 21.3}; /*C++11*/
1. 缩窄
初始化列表语法可防止缩窄,即禁止将数值赋给琺存储它的数值变量。
char c1 = 1.75e24; /*double-to-char, undefined behavior*/
char c2 = 459585821; /*int-to-char, undefined behavior*/
然而,如果使用初始化列表语法,编译器将禁止进行这样的类型转换,即将值存储到比它“窄”的变量中。
char c1 {1.75e24}; /*double-to-char, compile-time error*/
char c2 = {459585821}; /*int-to-char, out of range, compile-time error*/
但允许转换为更宽的类型。另外,只要值在较窄类型的取值范围内,将其转换为较窄的类型也是允许的。
char c1 {66}; /*int-to-char, in range, allowed*/
double c2 = {66}; /*int-to-double, allowed*/
2. std::initializer_list
C++11提供了模板类 initializer_list
,可将其用作构造函数的参数。
如果类有接受 initializer_list
作为参数的构造函数,则初始化列表语法就只能用于该构造函数。
列表中的元素必须是同一种类型或可转换为同一种类型。
STL容器提供了将 initializer_list
作为参数的构造函数:
vector<int> a1(10); /*uninitialized vector with 10 elements*/
vector<int> a2{10}; /*initializer-list, a2 has 1 element set to 10*/
vector<int> a3{10, 5, 2}; /*3 elements set to 10, 5, 2*/
头文件 initializer_list
提供了对模板类 initializer_list
的支持。
这个类包含成员函数 begin()
和 end()
,可用于获悉列表的范围。
除用于构造函数外,还可将 initializer_list
作用常规函数的参数。
#include <initializer_list>
double sum(std::initializer_list<double> i1);
int main(){
double total = sum({2.5, 3.1, 4}); /*4 converted to 4.0*/
}
double sum(std::initializer_list<double> i1)
{
double tot = 0;
for(auto p = i1.begin(); p != i1.end(); p++)
tot += *p;
return tot;
}