深入理解C++11 3.5 列表初始化

2019-10-31  本文已影响0人  zinclee123

3.5.1 初始化列表

C++98中,可以使用"{}"对数组元素进行统一的集合初始值设定,如

int arr[5] = {0};
int arr[] = {1,2,3,4};

而在C++11中可以如下初始化

int a[] = {1, 3, 5};            //C++98通过,C++11通过
int b[] {2, 4, 6};              //C++98失败,C++11通过
vector<int> c{1, 3, 5};          //C++98失败,C++11通过
map<int, float> d = {{1, 1.0f}, {2, 2.0f}, {3, 3.0f}, {4, 4.0f}}; //C++98失败,C++11通过

在C++11中,可以使用以下几种昂视完成初始化的工作:

后两种形式也可以用来获取堆内存new操作符中,如:

int* i = new int(1);
double* d = new double{1.2f};

标准模板库中容器对初始化列表的支持源自<initializer_list>。程序员只要#include<initializer_list>头文件,并且声明一个以initialize_list<T>模板类为参数的构造函数,也可以使得自定义的类使用列表初始化。如:

enum Gender {boy, girl};
class People {
public:
    People(initializer_list<pair<string, Gender>> l) {
        auto i = l.begin();
        for(; i != l.end(); ++i) {
            data.push_back(*i);
        }
    }
private:
    vector<pair<string, Gender>> data;
};

int main(){
    People ship2012 = {{"Garfield", boy}, {"HelloKitty", girl}};
}

同样,函数的参数列表也可以使用初始化列表,如:

void func(initializer_list<int> iv) {}

int main(){
    func({});
    func({1, 2});
}

初始化列表还可以用于函数返回的情况。注意,返回一个初始化列表,会导致构造一个临时变量,比如:

vector<int> func() {
    return {1, 3};
}

如果返回值是一个引用类型的哈,则会返回一个临时变量的引用,如:

const vector<int> & func1() {
    return {3, 5};
}

这里注意,必须要加const限制符。该规则与返回一个字面常量是一样的。

3.5.2 防止类型收窄

使用初始化列表最大优势是可以防止类型收窄(narrowing)。类型收窄是指一些可以使得数据变化或者精度丢失的隐式类型转换。包括:

类型收窄可以简单的理解为新类型无法表示原有类型数据的值的情况。在C++11中使用初始化列表进行初始化的数据编译器是会检查其是否发生类型收窄的,如:

char a = x;                 //收窄,但可以通过编译,IDE有提示Warning
char* b = new char(1024);    //收窄,但可以通过编译,IDE有提示Warning

char c = {x};              //收窄,无法通过编译
char d = {y};              //可以通过编译
unsigned char e {-1};       //收窄,无法通过编译

float f {7};               //可以通过编译
int g {2.0f};              //收窄,无法通过编译
float* h = new float{le48}; //收窄,无法通过编译
float i = 1.2l;            //可以通过编译

在C++11中,列表初始化是唯一一种可以防止类型收窄的初始化方式。

上一篇下一篇

猜你喜欢

热点阅读