C++メンバー初期化リスト

3768 ワード

C++メンバー初期化リスト
まず、メンバー初期化リストはコンストラクション関数にのみ使用できることを明らかにします.
1.メンバーを使用してリストを初期化する場合
I>非静的constメンバー変数の初期化
class A{
private:
    const int a;
public:
    A(); 
};

メンバー変数aを初期化するために構造関数をどのように記述しますか?そう思うかもしれない
A::A(){
    a = value;
}

実はこれは付与プロセスで、付与前に初期化が完了し、const変数は付与できません.初期化時に1つの値しか与えられません.
ここではメンバー初期化リストを使用し、メンバー初期化リストはどのように初期化するかを示します.
A::A() : a(value){}

II>メンバー参照の初期化
class A{
private:
    int &a;
public:
    A();
}

非静的constメンバーと同様に、左参照バインドの左値は初期化フェーズでのみ完了するため、ここではメンバー初期化リストを使用します.メンバー初期化リストは、どのように初期化するかを示します.
A::A() : a(left_value){}

III>ベースクラスメンバーの初期化
ベースクラス:
class ClassBase{
private:
    int a;
public:
    ClassBase();
    ClassBase(int a);
}

派生クラス:
class ClassDerived:public ClassBase{
private:
    ...        
public:
    ClassDerived(int x);
}

public継承はベースクラスのプライベートメンバーを継承するが、ベースクラスのインタフェースのみがアクセスできるため、派生クラスの構築関数では、付与値を単純に使用してベースクラスメンバーを初期化することはできない
したがって、派生クラスコンストラクタを実行する前に、ベースクラスのコンストラクタを実行します.
同様に、メンバー初期化リストを使用して、ベースクラスがどのように初期化されるかを表すことができます.すなわち、コンパイラがどのコンストラクション関数を呼び出してベースクラスメンバーを初期化するかを明示的に示すことができます.
呼び出しベースクラスのパラメトリック構造
ClassDerived::ClassDerived(int x):ClassBase(x){
    ...
}

ベースクラスの非パラメトリック構造を呼び出す
ClassDerived::ClassDerived() : ClassBase(){
    ...
}

ClassDerived::ClassDerived(){
    ...
}

メンバー初期化リストは、コンストラクション関数呼び出しプロシージャではなく、呼び出しのどちらを表し、メンバー初期化リストを追加しない場合は、ベースクラス呼び出しデフォルトコンストラクション関数(パラメトリックコンストラクション関数なし)を表します.
IV>他クラスのオブジェクトメンバーの初期化
class A {
public:
    A();
    A(int a);
    const A &operator=(const A &obj);
};

A::A() {
    cout << "A()" << endl;
}
A::A(int a) {
    cout << "A(int)" << endl;
}
const A &A::operator=(const A &obj) {
    cout << "A::operator=(const A &)" << endl;
    return obj;
}


class B {
private:
    A objA1;
    A objA2;
public:
    B();
};

BのオブジェクトのobjA 1とobjA 2をどのように初期化できますか?
1つ目
B::B() {
    objA1 = A();
    objA2 = A(3);
}

int main() {

    B objb;
    return 0;
}

出力:
A()                 
A()     
A()                     <<             
A::operator=(const A &) << objA1.operator=(       )
A(int)                  <<             
A::operator=(const A &) << objA2.operator=(       )

分割分析により、関数体を実行する前にデフォルトのコンストラクション関数が2回呼び出されたことがわかり、メンバー初期化リストを使用して、初期化フェーズ(コンストラクション関数体の実行前)でどのコンストラクション関数を呼び出すかを表すことができます.
B::B() : objA1(), objA2(3){}

出力:
A()
A(int)

デフォルトの非パラメトリック構造を呼び出す場合は、省略できます.
比較すると、メンバー初期化リストを使用する効率は、付与値よりもずっと高いことがわかります.
2.まとめてみる
I>メンバー初期化リストが初期化フェーズで機能する
基本タイプでは、初期化と付与には違いはありません.
クラスオブジェクトの場合:初期化リストは、呼び出しのデフォルトを表すどのコンストラクション関数を表し、初期化リストを書かないで呼び出します.
II>初期化フェーズが完了した後、コンストラクタを実行