web-dev-qa-db-ja.com

C ++-ヘッダー内の変数とコンストラクターを使用した変数の初期化

以下について、どちらを行う必要があるのですか、またはそれらはほぼ同等ですか?

class Something
{
    int m_a = 0;
};

class Something
{
    int m_a;
    Something(int p_a);
};

Something::Something(int p_a):m_a(p_a){ ... };
39
Evan Ward

あなたが投稿した2つのコードスニペットは等しくないです。

_class Something
{
    int m_a = 0;
};
_

ここでは、コンパイル時に初期化する値、つまり_0_を指定します。

_class Something
{
    int m_a;
    Something(int p_a);
};

Something::Something(int p_a):m_a(p_a){ ... };
_

そして、ここではそれを実行時(または実行時に)に実行し、値_p_a_はコンストラクタが呼び出されるまで不明です。

次のコードは、最初の例に近づいています。

_class Something
{
    int m_a;
    Something();
};

Something::Something() : m_a(0) { /* ... */ };
_

ここで考慮しなければならないのは、最初のケースでは、値がクラス定義に直接表示されることです。これにより、不要な依存関係が作成される可能性があります。 後で_0_を_1_に変更する必要がある場合はどうなりますか? Something::Something() : m_a(0)の部分は、ソースファイルにきちんとカプセル化され、ヘッダーファイルには表示されません。

_// Something.h - stable header file, never changed
class Something
{
    int m_a;
    Something();
};

// Something.cpp - can change easily
Something::Something() : m_a(0) { /* ... */ };
_

もちろん、クラス内の初期化の利点は、この欠点をはるかに上回ります。場合によります。あなたはそれを覚えておく必要があります。

47
Christian Hackl

最初の形式は、複数のコンストラクターがある場合(そして、それらすべてに同じ方法でメンバーを初期化させたい場合)、またはコンストラクターを作成する必要がない場合に、より便利です。

2番目は、イニシャライザがコンストラクタの引数に依存する場合、またはクラス内の初期化には複雑すぎる場合に必要です。また、コンストラクターが複雑な場合は、すべての初期化を1か所にまとめる方がよいでしょう。 (そして、C++ 11以前のコンパイラをサポートする必要がある場合にも必要です。)

14
Mike Seymour

最初の形式はC++ 11で新しく追加されたため、特にさまざまな古いコンパイラをサポートする必要がある場合は、現時点ではあまりサポートされていません。

それ以外の場合、C++ 11コンパイラが利用可能であれば、それらはほぼ同等です。

6
Mark B

クリスチャンハックルの答えについて詳しく説明します。

最初の形式では、m_aを初期化し、同時にデフォルトのc'torを設定できます。または、コードで明示的にして、defaultキーワードでコンストラクターを定義することもできます。

class Something
{       
    int m_a = 0;

    // explicitly tell the compiler to generate a default c'tor
    Something() = default;
};

2番目の形式では、自動生成されたデフォルトのc'torはm_aを初期化しないままにするため、ハードコードされた値に初期化する場合は、独自のデフォルトのc'torを作成する必要があります。

class Something
{
    int m_a;

    // implement your own default c'tor
    Something() : m_a(0) {}
};
3
Alexey Polonsky
class Something
{
    int m_a = 0;
};

に相当

class Something
{
    int m_a(0);
};

だから、やって

class Something
{
    int m_a;// (0) is moved to the constructor
public:
    Something(): m_a(0){}
};

ランタイム入力を必要とする、または必要としない初期化のための統一された構文を生成します。

最初のフォームは完全に誤解されている「宣言してから割り当て」のように見えるので、個人的には嫌いです。

0
user3528438

クリスチャンがコードを変更して同じようにした場合。これは、コンパイル時の最適化(Christianが完全に説明)と実行時の最適化の間のトレードオフです。

class Foo{

public: 
 Vector<double> vec1;
 .
 .
 .
  Vector<double> vecN;
}

事前定義されたdoubleで各ベクトルを初期化する必要があると想像してください。プログラムがこのクラスの多数のオブジェクトをインスタンス化する必要がある場合は、ランタイムを短縮してユーザーを満足させるために、ヘッダーファイルのベクターを初期化することをお勧めします。

0
hosh0425