web-dev-qa-db-ja.com

C ++コンストラクター名に続くコロンは何をしますか?

このコンストラクターでコロン演算子( ":")は何をしますか? MyClass(m_classID = -1, m_userdata = 0);と同等ですか?

class MyClass {
public:

    MyClass() : m_classID(-1), m_userdata(0) { 
    }

    int m_classID;
    void *m_userdata;
};
82
spencewah

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

コンストラクターの署名は次のとおりです。

_MyClass();
_

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

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

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

91
Daniel Daranas

これは初期化リストです。

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

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

フィールドの1つが参照である場合、オブジェクトの構築とコンストラクターの本体の間の短い時間であっても参照がnullになることはないため、初期化リストが必要です。次のエラーC2758が発生します: 'MyClass :: member_':コンストラクターのベース/メンバー初期化子リストで初期化する必要があります

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

唯一の正しい方法は次のとおりです。

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

これは、オブジェクトのメンバー変数を初期化するための初期化リストの始まりを示します。

に関して:MyClass(m_classID = -1, m_userdata = 0);

これは、引数を取ることができるコンストラクタを宣言します(したがって、MyClass m = MyClass(3, 4)を使用してMyClassを作成できます。これにより、_m_classID_が3、_m_userdata_が4になります) 。 MyClassコンストラクターに引数を渡さないと、初期化リストを持つバージョンに対して同等のオブジェクトが作成されます。

2
Dominic Rodger

初期化リストの開始を通知します。

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

2
JaredPar

初期化リスト です。あなたの例では、それはむしろこのようなものです(このようなもの-すべての場合で同等であるという意味ではありません):


class MyClass {

public:

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

    int m_classID;
    void *m_userdata;

};
1
Marcin Deptuła

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

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

コンストラクターは最初にメンバー変数を作成し、次にそれらに代入するため、コンストラクターの本体で代入することとまったく同じではありません。初期化では、作成時に初期値が提供されるため、複雑なオブジェクトの場合は、より効率的になります。

1
JohnMcG

それは正確に演算子ではありません。これは、コンストラクターの構文の一部です。

それが言っていることは、それに続くメンバー変数とそれらの初期値のリストになるということです。

定数メンバーはこの方法で初期化する必要があります。非定数は、単一の式で実行できる限り、ここでも初期化できます。メンバーを初期化するよりも多くのコードが必要な場合は、{}の間に実際のコードを挿入して実行する必要があります。

多くの人は、コンストラクタコードのほとんどすべてを初期化リストに入れたいと思っています。私は、イニシライザーの複数の画面で定期的にクラスを作成し、コンストラクターコードに「{}」を配置する同僚が1人います。

1
T.E.D.

オブジェクトの構築中にメンバー変数を設定する初期化リストの始まりです。あなたの例「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をご覧ください。

1
Patrick

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

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

0
SebastianK