12.6 Constructor member initializer lists


https://www.learncpp.com/cpp-tutorial/constructor-member-initializer-lists/
const変数はdeclareと同時に初期化しなければならないことを学びました
では、通常コンストラクション関数を使用するとどうなるのでしょうか.
class Something
{
private:
    const int m_value;

public:
    Something()
    {
        m_value = 1; // error: const vars can not be assigned to
    }
};
前のセクションでは、コンストラクション関数によってすべてのメンバー変数が作成されます.
初期化されていることがわかります
もしそうであれば、上記の場合にエラーが発生します.
const変数はdeclareと同時に初期化されないためです.
上の問題はどう解決すればいいですか.

Member initializer lists


c++でクラスのmember変数を宣言しながら値を割り当てるには、次の方法があります.
class Something
{
private:
    const int m_value;

public:
    Something(): m_value{ 5 } // directly initialize our const member variable
    {
    }
};
Somethingコンストラクタの横で初期化できます
したがって、上記のconst変数はエラーが発生しません.

Initializing array members with member initializer lists


array memberは以下のように初期化することもできる
class Something
{
private:
    const int m_array[5];

public:
    Something(): m_array {} // zero the member array
    {
    }

};
ただしc++11までは、上記のようにzero initだけでは不可能です
ただしc++11から完全に初期化できます
class Something
{
private:
    const int m_array[5];

public:
    Something(): m_array { 1, 2, 3, 4, 5 } // use uniform initialization to initialize our member array
    {
    }

};

Initializing member variables that are classes


クラスメンバー変数もinitできます
#include <iostream>

class A
{
public:
    A(int x = 0) { std::cout << "A " << x << '\n'; }
};

class B
{
private:
    A m_a {};
public:
    B(int y)
        : m_a{ y - 1 } // call A(int) constructor to initialize member m_a
    {
        std::cout << "B " << y << '\n';
    }
};

int main()
{
    B b{ 5 };
    return 0;
}
以上のコードの出力は以下の通りです.
A 4
B 5

Formatting your initializer lists


様々な方法でinit listを作成できます
class Something
{
private:
    int m_value1 {};
    double m_value2 {};
    char m_value3 {};

public:
    Something() : m_value1{ 1 }, m_value2{ 2.2 }, m_value3{ 'c' } // everything on one line
    {
    }
};
上のコードでは、1行にリストが存在します.
class Something
{
private:
    int m_value1;
    double m_value2;
    char m_value3;

public:
    Something(int value1, double value2, char value3='c') // this line already has a lot of stuff on it
        : m_value1{ value1 }, m_value2{ value2 }, m_value3{ value3 } // so we can put everything indented on next line
    {
    }

};
上のコードは下線とインデントでlistを書きます
class Something
{
private:
    int m_value1 {};
    double m_value2 {};
    char m_value3 {};
    float m_value4 {};

public:
    Something(int value1, double value2, char value3='c', float value4=34.6f) // this line already has a lot of stuff on it
        : m_value1{ value1 } // one per line
        , m_value2{ value2 }
        , m_value3{ value3 }
        , m_value4{ value4 }
    {
    }

};
上記のコードのように、行ごとに変数を初期化することもできます.

Initializer list order


メンバー変数宣言の順序でinitリストを作成する必要はありません
しかし、そうしないと、コンパイラに警告する可能性があります.
しかも順番をめちゃくちゃに書く理由もありません.
また、互いに依存性を確保するためにinitをしないでください.
注意:declareの順序(listを初期化する順序ではありません)
Init listのコマンドに従って初期化
依存項目を作成できます
しかし、私の意味はそうしないでください.
#include <iostream>
class Something
{
private:
     int m_value1;
     int m_value2;

public:
    Something() :  m_value1{ 2 }, m_value2{ m_value1 }
    {
       
    }
};
前述の符号化のように、m value 2{m value 1}は確かに正しい
でも反対ならゴミ代が必要です
#include <iostream>
class Something
{
private:
     int m_value1;
     int m_value2;

public:
    Something() :  m_value2{ 2 }, m_value1{ m_value2 }
    {
       
    }
};
前述したように、m value 1にはゴミ値が含まれています
リスト順ではなくdeclare順initなので

Summary


Member initializer lists allow us to initialize our members rather than assign values to them.
初期化ではなくassignで初期化できます
メンバーinitリストのおかげで
これは、コンストラクション関数を使用して初期化する唯一の方法です(宣言後の付与ではありません).