当前位置:嗨网首页>书籍在线阅读

04-统一的初始化

  
选择背景色: 黄橙 洋红 淡粉 水蓝 草绿 白色 选择字体: 宋体 黑体 微软雅黑 楷体 选择字体大小: 恢复默认

18.1.2 统一的初始化

C++11扩大了用大括号括起的列表(初始化列表)的适用范围,使其可用于所有内置类型和用户定义的类型(即类对象)。使用初始化列表时,可添加等号(=),也可不添加:

int x = {5};
double y {2.75};
short quar[5] {4,5,2,76,1};

另外,列表初始化语法也可用于new表达式中:

int * ar = new int [4] {2,4,6,7}; // C++11

创建对象时,也可使用大括号(而不是圆括号)括起的列表来调用构造函数:

class Stump
{
private:
    int roots;
    double weight;
public:
    Stump(int r, double w) : roots(r), weight(w) {}
};
Stump s1(3,15.6); // old style
Stump s2{5, 43.4}; // C++11
Stump s3 = {4, 32.1}; // C++11

然而,如果类有将模板std::initializer_list作为参数的构造函数,则只有该构造函数可以使用列表初始化形式。第3章、第4章、第9章、第10章和第16章讨论了列表初始化的各个方面。

1.缩窄

初始化列表语法可防止缩窄,即禁止将数值赋给无法存储它的数值变量。常规初始化允许程序员执行可能没有意义的操作:

char c1 = 1.57e27;   // double-to-char, undefined behavior
char c2 = 459585821; // int-to-char, undefined behavior

然而,如果使用初始化列表语法,编译器将禁止进行这样的类型转换,即将值存储到比它“窄”的变量中:

char c1 {1.57e27};     // 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,可将其用作构造函数的参数,这在第16章讨论过。如果类有接受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{4,6,1}; // 3 elements set to 4,6,1

头文件initializer_list提供了对模板类initializer_list的支持。这个类包含成员函数begin()和end(),可用于获悉列表的范围。除用于构造函数外,还可将initializer_list用作常规函数的参数:

#include <initializer_list>
double sum(std::initializer_list<double> il);
int main()
{
    double total = sum({2.5,3.1,4}); // 4 converted to 4.0
...
}
double sum(std::initializer_list<double> il)
{
    double tot = 0;
    for (auto p = il.begin(); p !=il.end(); p++)
        tot += *p;
    return tot;
}