0

初期化リストとは何か、そしてその使い方を学びましたが、まだ疑問に思っていました

初期化リストを使用してクラスの変数を初期化することと、コンストラクターで自分で行うことの違いは何ですか?

例えば

class MyClass {
public:

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

    int m_classID;
    void *m_userdata;
};

VS

class MyClass {
public:

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

    int m_classID;
    void *m_userdata;
};

コードを読み書きしやすくするのは単なる設計上の習慣ですか、それとも他の特定の理由がありますか?

4

6 に答える 6

3

これらの変数が基本型であり、const参照でも参照でもない場合、違いはありません。

メンバーが参照である場合、またはそれがである場合、それらconst初期化する必要があります。これは、基本型の初期化されていない参照または変数の作成を禁止するのと同じ理由で、初期化リストを介してのみ行うことができます。const

int& x; // ERROR!
const int y; // ERROR!

これらのオブジェクトは、初期化後に再度割り当てることはできません。したがって、値を初期化する必要があり、初期化されていないメンバー変数を使用してクラスのコンストラクターの本体を実行できないことは理にかなっています。

したがって、選択肢がある場合、基本型の場合、2 つの形式に違いはありませ。選択肢がない状況があることを覚えておいてください。

一方、メンバー変数がクラス typeの場合、違いは、初期化リストがないと、デフォルトで構築され (可能であれば) 、コンストラクターの本体に割り当てられることです初期化リストを使用すると、指定した引数で直接構築されます。

C++11 では追加の可能性があることに注意してください。

class MyClass {
public:
    int m_classID = -1;
    void *m_userdata = nullptr;
};
于 2013-03-10T22:08:09.047 に答える
2

初期化子リストを使用すると、メンバー変数のコンストラクターを呼び出すことができます。

コンストラクターの本体で初期化する場合は、コンストラクターではoperator=なく (代入) を呼び出しています。

この違いは、次の 2 つの形式の違いに似ています。

int three(3);            // Constructor argument
int three; three = 3;    // Assignment after construction

これは、既定のコンストラクターを持たないメンバー (つまり、引数のないコンストラクター) と、作成時に値を設定する必要があるメンバー (参照や定数など) に違いをもたらします。

そのため、コンストラクター本体で特定の種類のメンバーのみを初期化することができます。ただし、すべての種類のメンバーを初期化子リストで初期化できます。これと、初期化子リストで初期化されたメンバーに対してデフォルトのコンストラクターが呼び出されないという事実 (複雑なオブジェクトでは違いがありますが、たとえば整数では問題になりません) は、一般的に初期化子を使用する方が望ましいことを意味します。選択肢を与えられたリスト。

于 2013-03-10T22:08:49.717 に答える
1

あなたが与える場合、直接の違いはありません-初期化リストが実際に初期化される順序(メンバーが宣言される順序)にわずかな違いがあります。2番目の例では、次のように言っm_classID=-1ている行を交換する場合、m_userdata = 0彼らは確かに彼が反対の順序で初期化したでしょう。

イニシャライザリストの外部で参照またはconst値を初期化することはできないため、次のようになります。

class bleh
{
   int& m_x;
   bleh(int x)
   {
      m_x = x;
   }
};

ある種のエラーが発生します。

class bleh
{
   int& m_x;
   bleh(int x): m_x(x)
   {
   }
};

正しい方法です。

于 2013-03-10T22:10:51.693 に答える
1

C ++ 11の違いを指摘するだけです:

class MyClass {
public:
    MyClass(std::string str) : m_str(str) { }
private:
    std::string m_str;
};

することと同等です

class MyClass {
public:
    MyClass(std::string str) { m_str = std::move(str); }
private:
    std::string m_str;
};

一方:

class MyClass {
public:
    MyClass(std::string str) { m_str = str; }
private:
    std::string m_str;
};

代入演算子を呼び出すだけです。

Lua でオブジェクトを初期化していたため、この問題に遭遇しました。オブジェクトが破壊されているときに、文字列が 2 回クリーンアップされ、Lua が渡された文字列の所有権を制御していると考えたため、sigtrap が発生しましたが、移動すると、それはもはや場合。

これが質問に完全には答えていないことは知っていますが、他の答えはこれを直接扱っていませんでした。

于 2014-01-14T14:47:49.687 に答える
0

初期化リストが望ましい理由は

  1. 参照して使用できます
  2. デフォルトのコンストラクター+operator=を実行することは避け、より高速な必要なコンストラクターを実行します。デフォルトのコンストラクターがプライベートの場合は、初期化子リストを使用する必要があります
于 2013-03-10T22:12:19.490 に答える
0

参照メンバーなど、MIL なしでは初期化できないものがあります。

class MyClass {
public:

    MyClass(MyOtherClass& otherClass)
         : m_classID(-1)
         , m_userdata(otherClass)
    { 
    }

    int m_classID;
    MyOtherClass& m_userdata;
};

また、const メンバーを intizlize する唯一の方法です。

于 2013-03-10T22:08:27.363 に答える