在C++11中,使用{}可進行如下各項的初始化:
- 類成員快速初始化
- 數組、集合(列表)初始化
- 自定義類型初始化
C++11可以將{}初始化器用於任何類型(可以使用等號,也可以不適用),這是一種通用的初始化語法。
集合、函數
在C++11中,集合(列表)的初始化已經成為C++的一個基本功能,被稱為“初始化列表(initializer list)”
示例代碼:
int a[] = { 1, 2, 3 }; //C++98支持,C++11支持 int b[]{2, 3, 4}; //C++98不支持,C++11支持 vector<int> c{ 1, 2, 3 }; //C++98不支持,C++11支持 map<int, float> d = {{ 1, 1.0f }, { 2, 2.0f }, { 3, 3.0f } };//C++98不支持,C++11支持
在C++11中,自動變量和全局變量的初始化方式包括:
- 等號=加上賦值表達式(assignment-expression),例如:int a=2+3;
- 等號=加上花括號表達式的初始化列表,例如:int a = {3+4};
- 圓括號式的表達式列表(expression-lit),例如:int a(6+8);
- 花括號式的初始化列表:例如:int a{6+8};
最后兩種形式也可以用於獲取堆內存new操作符中,例如:
int* i = new int(1); double* d = new double(1.2f);
標准模板庫STL中容器對初始化列表的支持源於<initializer_list>頭文件中initialize_list類模板的支持。程序員只要#include<initializer_list>並聲明一個以initialize_List<T>模板類為參數的構造函數,也可以使得自定義類使用列表初始化。
enum Gender{ boy, girl }; class People { public: //initializer_list的構造函數 People(initializer_list<pair<string, Gender>> ll) { auto iter = ll.begin(); for (; iter != ll.end(); ++iter) { data.push_back(*iter); } } private: vector<pair<string, Gender>> data; }; //函數的參數列表使用初始化列表 void Fun(initializer_list<int> iv){}
上述代碼中,為People類定義了一個使用initializer_list<pair<string,Gender>>模板類作為參數的構造函數,使用C++11的auto關鍵字來自動類型推斷。
可以使用{}以如下的方式初始化:
People people = { { "Garfield", boy }, { "HelloKitty", girl } };
上述代碼也定義了一個使用initializer_list<int>為參數的函數,也可以使用初始化列表:
Fun({ 1, 2 }); Fun({});//空列表
同理,類和結構體的成員函數也可以使用初始化列表,包括一些操作符的重載函數。示例代碼:
class Mydata { public: Mydata & operator[] (initializer_list<int> input) { for (auto i = input.begin(); i != input.end(); ++i) { idx.push_back(*i); } return *this; } Mydata & operator = (int v) { if (idx.empty() != true) { for (auto i = idx.begin(); i != idx.end(); ++i) { d.resize((*i > d.size()) ? *i : d.size()); d[*i - 1] = v; } idx.clear(); } return *this; } void print() { for (auto i = d.begin(); i != d.end(); ++i) { cout << *i << " "; } cout << endl; } private: vector<int> idx;//輔助數組,用於記錄index vector<int> d; };
Mydata mydata;
mydata[{2, 3, 5}] = 7;
mydata[{1, 4, 5, 8}] = 4;
mydata.print();
另外,初始化列表頁可以用於函數返回的情況,與聲明時使用列表初始化一樣,列表初始化構造成什么類型是依據返回類型的:
vector<int> Func() { return{ 1, 3 }; }
類成員初始化
C++98中,對於類中的靜態成員常量,可以使用等號“=”加初始值的方式進行初始化,稱為“就地”聲明。在C++98中要求較高:如果靜態成員不滿足常量性,不能就地聲明,且而且即使常量的靜態成員也只能是整型或枚舉型才能就地初始化。
在C++11中,除了初始化列表(在構造函數中初始化)外,允許使用等=或花括號{}進行就地的非靜態成員變量初始化,例如:
struct example { int a = 1; double b{ 1.2 }; };
注意:
如果在一個類中,既使用了就地初始化來初始化非靜態成員變量,又在構造函數中使用了初始化列表,執行順序是:先執行就地初始化,然后執行初始化列表。
注意執行順序可能導致的問題。
參考:
《深入理解C++11》
《C++ Primer Plus 6th》