読者です 読者をやめる 読者になる 読者になる

ぷろみん

プログラミング的な内容を扱ってます

メンバ初期化子

モチベーション

メンバのコンストラクタ初期化子と宣言初期化子って役割被ってるので、どういう時にどっちを使った方が素敵か考えてみました。

コンストラクタ初期化子

class Foo{
public:
    Foo()
    // コンストラクタ初期化子
        : a_(0)
    {}

private:
    int a_;
};

コンストラクタで初期化します。

宣言初期化子

struct Foo{
public:
    Foo(){}

private:
    // 宣言初期化子
    int a_ = 0;
};

メンバに初期化値を与えます。

どちらを使うべきか

見たら分かる通り圧倒的に宣言初期化子を使った方が見通しも良いし分かりやすいです。宣言初期化子を使いましょう。

コンストラクタ初期化子の使い道

コンストラクタ引数を初期化に必要とする場合はコンストラクタ初期化子を使うしかありません。

class Foo{
public:
    // 宣言初期化子ではaを取得できない
    Foo(int a) : a_(a) {}

private:
    int a_;
};

依存関係を減らしたい場合はコンストラクタ初期化子を使いましょう。

// foo.h
class Bar;

class Foo{
public:
    Foo();

private:
    // 宣言初期化子では不完全型は使えない
    // std::unique_ptr<Bar> bar_( new Bar );
    std::unique_ptr<Bar> bar_;
};
// foo.cpp
Foo::Foo() : bar_( new Bar ) {
}

初期化順

初期化順はメンバの順番で行われます。

struct Foo {
    // 宣言初期化子だと順番なので分かりやすい
    int a_ = 0; // 1
    int b_ = 1; // 2
    int c_ = 2; // 3
};
struct Foo {
    // コンストラクタ初期化子の順番に依存しないので分かりにくい
    Foo() :
        c_(2), // 3
        b_(1), // 2
        a_(0)  // 1

    int a_;
    int b_;
    int c_;
};

依存関係を持った初期化では積極的に宣言初期化子を使いましょう。