2017-10-04 7 views
0

ここでは非常に広範に議論されている主題ですが、私はリストの初期化とC++のinitializer_listsに関するすべての混乱を取り除く徹底的な答えを見つけるのは苦労しました。私はそれに試してみて、私自身の質問をします。これら2つの初期化リストは同様に振る舞う理由を私は理解していないリストの初期化、Initializer_listおよび関連する質問をC++で

class C 
{ 
public : 
    C(int a, int b, int c) : _a (a), _b(b), _c(c) {}; //initialization_list with() 
    //C(int a, int b, int c) : _a{ a }, _b{ b }, _c{ c } {}; //initialization list with {} 
private : 
    int _a, _b, _c; 
}; 

int main() 
{ 
    C a(5.3,3.3,4.3); // no list 
    C b{5.3,3.3,4.3}; // list {} 
    C c({5.3,3.3,4.3}); // list {} 
} 

してください、次のコードスニペットを検討?コンパイルエラーを取得するために、タイプ_a{a}, _b{b}, _c{c}の初期化リストを使用して、タイプCのオブジェクトを作成しようとすると、予想していました。しかし、エラーは発生せず、_a, _b and _cは整数値を格納するだけです。

コンパイラがナローイングエラーメッセージを生成するリスト "{}"を使用してオブジェクトbまたはcを作成するときのみです。何故ですか?私が気付いていない{}や()を使って初期化リストを書くことと、動作が同じであることの間には、何らかの違いがありますか?

class C 
{ 
public : 

//private : 
    int _a, _b, _c; 
}; 

int main() 
{ 
    C a(5,3,4); //obviously doesn't work as no such constructor 
    C b{5,3,4}; //work only if _a, _b and _c are not private nor protected! 
} 

どの変数が公開されている場合(括弧付き)は、第2の文は、のみ動作することを来る:

は私の次の質問に来ますか?関与するメカニズムは何ですか?

「狭く安全」このリストメカニズムは提供しません {}、他のどのような「機能」リストでオブジェクトを作成することによって、提供のそばだから私は、よりよく理解したいと思いますか? 2番目の呼び出しでは、それはまだ呼び出されるデフォルトのコンストラクタなので(つまり、引数としてinitializer_listをとるデフォルトのコンストラクタではありません)、そうですか?

最後に、私のclass Cを想像してください。別のコンストラクタがパラメータとして初期化子リストを取得しました。

class C 
    { 
    public : 
     C() = default; //default constructor 
     C(int a, int b, int c) : _a (a), _b(b), _c(c) {}; 
     C(std::initializer_list<int> a) { //do some stuffs with the list}; 
    private : 
     int _a, _b, _c; 
    }; 

これは、整数の任意の数字を取ってオブジェクトを作成しようとしているが、3(または実際には0)場合、initializer_listを取るコンストラクタが呼び出される、ということは明らかです。しかし、そのようなオブジェクト作成する場合:

C c(); 

または

C c{}; 

をデフォルトコンストラクタが呼び出されます。しかし、正確に整数を持つオブジェクト作成場合:

C c(5,2,3); 

または

C c{5,2,3}; 

initializer_listコンストラクタが呼び出されますが。デフォルトコンストラクタまたは初期化子リストのコンストラクタのどちらかを呼び出すことができれば初期化子リストコンストラクタと「普通のコンストラクタ」の両方ができればデフォルトコンストラクタ

  • を好む、

    • :ルールは、そのようになります私はそのように私のオブジェクトを作成した場合、初期化子リストのコンストラクタしたがって

    を好む(と私が間違っているなら、私を修正)、呼び出される:

    C c{5,3,4}; 
    

    iniatializer-listコンストラクタが呼び出されます。しかし、私のようなオブジェクトを作成する場合:

    C c(5,3,4); 
    

    2番目のコンストラクタ(引数として3つのintsを取る)が呼び出されます。私の質問です:どのように私は狭い安全性を提供したい場合は、iniatializer - リストの代わりに、この2番目のコンストラクタでオブジェクトを作成することができますか? (なぜなら、この質問の最初の例のように、イニシャライザリストコンストラクタが代わりに呼び出されるからです)。

    あなたの返信を証明することを躊躇しないで、この質問では私が話していないリスト関連の概念について議論してください。私はそれらを非常によく把握したいと思います。ありがとう。

  • +2

    [std :: initializer_list'](http:// ja)の[コンストラクタメンバ初期化リスト](http://en.cppreference.com/w/cpp/language/initializer_list) .cpp参照。com/w/cpp/utility/initializer_list)と[list initialization](http://en.cppreference.com/w/cpp/language/list_initialization)を参照してください。それらは3つの異なるものです。 –

    答えて

    1

    中括弧はいつでも使用されます。aggregate initialization、順番に初期化する構造体またはクラスの初期化メソッド、または指定子を使用しています。例えば、

    ここ
    #include <iostream> 
    
    struct Foo 
    { 
        int a; 
        char b; 
    }; 
    
    class Doo 
    { 
    public: 
        double h; 
        char ch; 
    }; 
    
    int main() { 
        Foo first = {3, 't'}; 
        std::cout << first.b << "\n"; 
        //t 
        Doo second = {'3', 50}; 
        std::cout << second.ch << "\n"; 
        //2 interpreted as char 
    } 
    

    、私たちはクラスまたは構造体を初期化するために{}を使用して、彼らは常にクラスに記載されているためであると解釈されます。 ASCIIで50文字が文字 '2'に対応しているので、 '2'が印刷されたのです。

    コンストラクタの初期化

    あなたはまた、コンストラクタの初期化リストをここで

    #include <iostream> 
    
    struct Pair 
    { 
        int first; 
        long second; 
    }; 
    
    class Couple 
    { 
    public: 
        Pair p; 
        int g; 
    public: 
    Couple(): p{3, 700}, g{3} 
    {} 
    }; 
    
    int main() { 
        Couple test; 
        std::cout << test.p.first << "\n"; 
        //3 
    } 
    

    を同じロジックを使用することができますので、p{3, 700}は、どこで他に使用Pair p = {3, 700};と同じになりますコード。あなたは基本的に集計初期化を使用しています。さて、ペアフィールドの中括弧をカッコに変更するとどうなりますか?

    我々は2つの数値を受け入れ、ペアのコンストラクタを持っていないためです。このエラー

    main.cpp: In constructor 'Couple::Couple()': 
    main.cpp:15:26: error: no matching function for call to 'Pair::Pair(int, int)' 
        Couple(): p(3, 700), g{3} 
    

    を取得します。したがって、集約初期化と括弧の主な違いは、括弧で指定した特定の引数セットに対してコンストラクタを実装する必要がありますが、中括弧ではコンパイラがデフォルトのものを使用できます。

    std :: initializer_listは、{}の初期化リストの複数の引数のコンテナではあまり使用されない形式です。

    関連する問題