1. ホーム
  2. c++

[解決済み] C++11の新機能である宣言時のメンバー初期化機能により、初期化リストは廃止されたのでしょうか?

2023-07-01 14:30:42

質問

C++11では、ヘッダー宣言でクラスメンバを初期化できるようになりました。

class aClass
{
    private:
        int mInt{100};
    public:
         aClass();
        ~aClass();
};

というわけで、ちょっと混乱しています。伝統的にコンストラクタの初期化リストはメンバの初期化のために使用されてきました。

aClass::aClass()
: mInt(100)
{
    ...
}

C++11 の新しい宣言時のメンバー初期化機能により、初期化リストは廃止されたのでしょうか?そうでない場合、どちらか一方の利点は何ですか?宣言時の初期化が有利な状況、あるいは初期化リストが有利な状況とはどのようなものでしょうか。また、どのような場合にどちらを使うべきでしょうか?

どのように解決するのですか?

いいえ、この記事のように陳腐化することはありません。 C++11 の新しい初期化フォームを理解する で述べているように クラス メンバの初期化 セクションに書かれています ( 強調 ):

同じデータメンバがクラスメンバイニシャライザとmem-initの両方をコンストラクタに持つ場合、後者が優先されることを覚えておいてください。実際には にデフォルト値を指定することで、この動作を利用することができます。 をクラスメンバーイニシャライザの形で指定することで、 この挙動を利用することができます。そうでない場合は、コンストラクタの mem-init が有効になり、クラスメンバイニシャライザをオーバーライドします。 このテクニックは複数のコンストラクタを持つクラスで有用です。

クラスメンバーの初期化は便利ですが、初期化リストの必要性がなくなるわけではなく、両方の機能が一緒になって、デフォルト値を指定し、必要なときにそれをオーバーライドする素晴らしい方法を提供します。これはまた Bjarne Stroustrup もそう考えているそうです。

<ブロッククオート

これはタイピングを少し節約しますが、本当の利点は複数のコンストラクタを持つクラスで得られます。多くの場合、すべてのコンストラクタはメンバに対して共通のイニシャライザを使用します。

で、共通のイニシャライザを持つメンバの例を示します。

class A {
  public:
    A(): a(7), b(5), hash_algorithm("MD5"), s("Constructor run") {}
    A(int a_val) : a(a_val), b(5), hash_algorithm("MD5"), s("Constructor run") {}
    A(D d) : a(7), b(g(d)), hash_algorithm("MD5"), s("Constructor run") {}
    int a, b;
  private:
    HashingFunction hash_algorithm;  // Cryptographic hash to be applied to all A instances
    std::string s;                   // String indicating state in object lifecycle
};

と言うようにします。

hash_algorithmとsがそれぞれ単一のデフォルトを持っているという事実は、コードの混乱の中で見失われ、メンテナンス時に容易に問題になりえます。その代わり、データメンバの初期化を因数分解してしまえばよいのです。

class A {
  public:
    A(): a(7), b(5) {}
    A(int a_val) : a(a_val), b(5) {}
    A(D d) : a(7), b(g(d)) {}
    int a, b;
  private:
    HashingFunction hash_algorithm{"MD5"};  // Cryptographic hash to be applied to all A instances
    std::string s{"Constructor run"};       // String indicating state in object lifecycle
};

注意:C++11での不利な点

C++11 でクラス内のメンバ初期化を使用すると、クラスが非集約化されるため、1 つの欠点があります。 集合体初期化 これは意外かもしれません。この制限は C++14 では撤廃されましたが、その限りではありません。参照してください。 C++11 非静的メンバ初期化子を持つクラスに対する集約的初期化 を参照してください。