1. 程式人生 > 實用技巧 >C++11使用{}大括號初始化

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》