2009-08-13 7 views

答えて

79

これは初期化リストで、コンストラクタの実装の一部です。

コンストラクタのシグネチャは次のとおりです。

MyClass(); 

これは、コンストラクタは、パラメータなしで呼び出すことができることを意味します。これにより、デフォルトのコンストラクタがになります。つまり、MyClass someObject;を書くときにデフォルトで呼び出されるコンストラクタです。

部分: m_classID(-1), m_userdata(0)は、初期化リストと呼ばれます。これは、あなたのオブジェクトのいくつかのフィールド(必要に応じてそれらのフィールド)を、未定義のままではなく、選択した値で初期化する方法です。

初期化リストを実行すると、コンストラクタ本体(あなたの例では空の状態になります)が実行されます。その内部にはさらに多くの代入を行うことができますが、一度入力すると、すべてのフィールドが既に初期化されています(ランダム、未指定の値、または初期化リストで選択したフィールド)。つまり、コンストラクタ本体で行う代入は初期化ではなく、値の変更になります。

2

これは、オブジェクトのメンバー変数を初期化するための初期化子リストの先頭を示します。 (私はm_classIDが3であることにつながるれ、MyClass m = MyClass(3, 4)を使用してMyClassを作成することができ、そしてm_userdataは4である)の引数を取ることができ、コンストラクタを宣言していMyClass(m_classID = -1, m_userdata = 0);

:に関しては

MyClassコンストラクタに引数を渡さないと、初期化子リストを持つバージョンと同等のオブジェクトが作成されます。

0

この場合、はい、istはプリミティブ型のみが関係するため同等です。

メンバーがクラス(構造体)の場合は、初期化リストを使用する必要があります。これは、オブジェクトがデフォルトで構築されてから割り当てられるためです。

1

initialization listです。あなたの例では、むしろこのような何か(このようなもの - それはすべてのケースで同等だという意味ではありません)です:


class MyClass { 

public: 

    MyClass(){ 
     m_classID = -1; 
     m_userdata = 0; 
    } 

    int m_classID; 
    void *m_userdata; 

};
2

イニシャライザリストの先頭に信号を送ります。

また、MyClass(m_classId = -1、m_userData = 0)と同等ではありません。これは、デフォルト値を持つ2つのパラメータを持つコンストラクタを定義しようとしています。しかし、値には型がなく、まったくコンパイルしないでください。

1

これは、メンバ初期化リストと呼ばれます。これは、スーパークラスのコンストラクタを呼び出すために使用され、メンバ変数には作成時の初期値が与えられます。

この場合、m_classIDを-1に、m_userDataをNULLに初期化しています。

コンストラクタのボディに代入するのは、メンバ変数を作成してから代入するためではありません。初期化では、作成時に初期値が提供されるため、複雑なオブジェクトの場合はより効率的になります。

+1

それは時には、使用する必見です:唯一の正しい方法は、コンストラクタベース/メンバー初期化子リストで

class MyClass { public : MyClass(std::string& arg) { member_ = arg; } std::string& member_; }; 

初期化する必要がありますメンバ初期化リスト。参照変数のメンバ変数がある場合は、メンバ初期化リストを使用してそれを設定する必要があります。 – Skurmedel

1

正確にはオペレータではありません。これはコンストラクタの構文の一部です。

次のことは、メンバー変数とその初期値のリストになるということです。

このように定数メンバーを初期化する必要があります。非定数は、単一の式で行うことができる限り、ここでも初期化することができます。メンバを初期化するためにそれ以上のコードが必要な場合は、{}の間に実際のコードを置く必要があります。

多くの人がinitilizerリストにすべてのコンストラクタコードを入れたいと思っています。私は、いくつかの初期画面のクラスで定期的にクラスを書く1人の同僚を持っていて、コンストラクタコードに "{}"を入れます。

1

オブジェクトの構築中にメンバー変数を設定する初期化子リストの開始点です。あなたの例 "MyClass(m_classID = -1、m_userdata = 0);"

MyClass(int classId = -1, void* userData = 0) : m_classID(classId), m_userdata(userData) {} 

初期化子リストがより良いと考えられている:あなたは正しいコンストラクタを定義していないとあなたはとにかくパラメータリストにメンバ変数にアクセスすることはできないであろうと、あなたのようなものを持っている可能性が...ことはできません:

MyClass(int classId = -1, void* userData = 0) { 
    m_classID = classId; 
    m_userdata = userData; 
} 

Googleについて詳しくは、

37

初期化リストです。

コンストラクタの本体に入るまでに、すべてのフィールドは既に構築されています。彼らがデフォルトコンストラクタを持っている場合、それらはすでに呼び出されています。ここでコンストラクタの本体に値を代入すると、コピー代入演算子が呼び出されます。これは、オブジェクトにリソースがある場合はリソース(メモリなど)を解放して再取得することを意味します。

したがって、intのようなプリミティブ型の場合、コンストラクタのボディにそれらを割り当てる利点はありません。コンストラクタを持つオブジェクトの場合は、1つではなく2つのオブジェクトの初期化を行わないため、パフォーマンスの最適化が行われます。

オブジェクトの構築とコンストラクタの本体の間の短い時間内であっても参照がnullになることはないため、フィールドの1つが参照の場合は初期化リストが必要です。 「MyClassの:: member_」:以下はエラーC2758を発生させ

class MyClass { 
public : 
    MyClass(std::string& arg) 
     : member_(arg) 
    { 
    } 
    std::string& member_; 
}; 
+2

参照メンバがあれば、コンストラクタの初期化子リストを持つコンストラクタを定義する必要があると誤解されることがよくあります。しかしそれは事実ではありません。単純な 'MyClass m = {arg};'もうまく動作します。 –

+0

litb:しかし、あなたは多かれ少なかれm = {arg}を使う必要があります。あなたarent 'ですか?私の目では、MyClass m(ref)を行うことができることが非常に求められています。 – Skurmedel

+0

@Skurmedel、私は同意します。しかし、それがそれを行う唯一の方法だとは限りません。確かに; –

関連する問題