【C++2.0新特性】统一的初始化

Posted by LudoArt on September 10, 2019

统一的初始化

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;
}