Initializer List は、クラスのデータ メンバーを初期化する際に使用されます。初期化されるメンバーのリストは、コロンが後に続くコンマ区切りのリストとしてコンストラクターで指定されます。以下は、初期化リストを使用して Point クラスの x と y を初期化する例です。
例
C++
#include> using> namespace> std;> class> Point {> private>:> >int> x;> >int> y;> public>:> >Point(>int> i = 0,>int> j = 0): x(i), y(j) {}> >/* The above use of Initializer list is optional as the> >constructor can also be written as:> >Point(int i = 0, int j = 0) {> >x = i;> >y = j;> >}> >*/> >int> getX()>const> {>return> x; }> >int> getY()>const> {>return> y; }> };> int> main()> {> >Point t1(10, 15);> >cout <<>'x = '> << t1.getX() <<>', '>;> >cout <<>'y = '> << t1.getY();> >return> 0;> }> |
>
>出力
x = 10, y = 15>
上記のコードは、Initializer リストの構文の単なる例です。上記のコードでは、x と y をコンストラクター内で簡単に初期化することもできます。ただし、コンストラクター内のデータ メンバーの初期化が機能せず、Initializer List を使用する必要がある状況があります。そのような場合は次のとおりです。
1. 非静的constデータメンバの初期化の場合
const データ メンバーは、Initializer List を使用して初期化する必要があります。次の例では、 t は Test クラスの const データ メンバーであり、Initializer List を使用して初期化されます。初期化子リストで const データ メンバーを初期化する理由は、const データ メンバーに個別にメモリが割り当てられず、シンボル テーブル内で折り畳まれるため、初期化子リストで初期化する必要があるためです。
また、これはパラメーター化されたコンストラクターであり、代入演算子を呼び出す必要がないため、余分な操作が 1 つ回避されます。
例
C++
// C++ progmram to demonstrate the use of> // initializer list to initialize the const> // data member> #include> using> namespace> std;> class> Test {> >const> int> t;> public>:> >//Initializer list must be used> >Test(>int> t):t(t) {}> >int> getT() {>return> t; }> };> int> main() {> >Test t1(10);> >cout< return 0; }> |
>
>出力
10>
2. 参照メンバの初期化について
参照メンバーは、Initializer List を使用して初期化する必要があります。次の例では、 t は Test クラスの参照メンバーであり、Initializer List を使用して初期化されます。
例
C++
C++で優先キュー
// Initialization of reference data members> #include> using> namespace> std;> class> Test {> >int> &t;> public>:> >Test(>int> &t):t(t) {}>//Initializer list must be used> >int> getT() {>return> t; }> };> int> main() {> >int> x = 20;> >Test t1(x);> >cout< x = 30; cout< return 0; }> |
>
>出力
20 30>
3. デフォルトコンストラクターを持たないメンバーオブジェクトの初期化の場合
次の例では、クラス A のオブジェクト a はクラス B のデータ メンバーであり、A にはデフォルトのコンストラクターがありません。初期化には初期化子リストを使用する必要があります。
例
C++
// C++ progmam to initialize a member object without default> // constructor> #include> using> namespace> std;> class> A {> >int> i;> public>:> >A(>int>);> };> A::A(>int> arg)> {> >i = arg;> >cout <<>'A's Constructor called: Value of i: '> << i> ><< endl;> }> // Class B contains object of A> class> B {> >A a;> public>:> >B(>int>);> };> B::B(>int> x) : a(x)> {>// Initializer list must be used> >cout <<>'B's Constructor called'>;> }> int> main()> {> >B obj(10);> >return> 0;> }> |
>
>出力
A's Constructor called: Value of i: 10 B's Constructor called>
クラス A にデフォルト コンストラクターとパラメーター化コンストラクターの両方がある場合、デフォルト コンストラクターを使用して を初期化する場合、Initializer List は必須ではありませんが、パラメーター化コンストラクターを使用して を初期化する場合は必須です。
4. 基本クラスのメンバーの初期化の場合
ポイント 3 と同様、基本クラスのパラメーター化されたコンストラクターは、Initializer List を使用してのみ呼び出すことができます。
例
C++
#include> using> namespace> std;> class> A {> >int> i;> public>:> >A(>int> );> };> A::A(>int> arg) {> >i = arg;> >cout <<>'A's Constructor called: Value of i: '> << i << endl;> }> // Class B is derived from A> class> B: A {> public>:> >B(>int> );> };> B::B(>int> x):A(x) {>//Initializer list must be used> >cout <<>'B's Constructor called'>;> }> int> main() {> >B obj(10);> >return> 0;> }> |
>
>出力
A's Constructor called: Value of i: 10 B's Constructor called>
5. コンストラクタのパラメータ名がデータメンバと同じ場合
コンストラクターのパラメーター名がデータ メンバー名と同じ場合、データ メンバーは次のいずれかを使用して初期化する必要があります。 このポインタ またはイニシャライザリスト。次の例では、A() のメンバー名とパラメーター名は両方とも i です。
例
C++
#include> using> namespace> std;> class> A {> >int> i;> public>:> >A(>int>);> >int> getI()>const> {>return> i; }> };> A::A(>int> i) : i(i)> {> }>// Either Initializer list or this pointer must be used> /* The above constructor can also be written as> A::A(int i) {> >this->私 = 私;>> }> */> int> main()> {> >A a(10);> >cout << a.getI();> >return> 0;> }> |
>
>出力
10>
6. パフォーマンス上の理由から
本体内で値を割り当てるのではなく、Initializer List ですべてのクラス変数を初期化することをお勧めします。次の例を考えてみましょう。
例
C++
// Without Initializer List> class> MyClass {> >Type variable;> public>:> >MyClass(Type a) {>// Assume that Type is an already> >// declared class and it has appropriate> >// constructors and operators> >variable = a;> >}> };> |
>
>
ここで、コンパイラは次の手順に従って MyClass 型のオブジェクトを作成します。
1. 型のコンストラクターが最初に a に対して呼び出されます。
2. デフォルトの構成変数
3. Type の代入演算子は、MyClass() コンストラクターの本体内で呼び出され、代入されます。
variable = a;>
4. そして最後に、スコープ外に出るため、 Type のデストラクターが呼び出されます。
ここで、Initializer List を含む MyClass() コンストラクターを使用した同じコードを考えてみましょう。
C++
// With Initializer List> class> MyClass {> >Type variable;> public>:> >MyClass(Type a):variable(a) {>// Assume that Type is an already> >// declared class and it has appropriate> >// constructors and operators> >}> };> |
mysqlワークベンチの使い方
>
>
Initializer List を使用すると、コンパイラは次の手順に従います。
1. 型のコンストラクターが最初に a に対して呼び出されます。
2. Type クラスのパラメーター化されたコンストラクターが呼び出され、初期化されます: variable(a)。初期化子リストの引数は、構成変数を直接コピーするために使用されます。
3. Type のデストラクターは、スコープ外になるため、 a に対して呼び出されます。
この例からわかるように、コンストラクター本体内で代入を使用すると、コンストラクター + デストラクター + 1 つの追加代入演算子の呼び出しという 3 つの関数呼び出しが行われます。また、Initializer List を使用する場合、関数呼び出しはコピー コンストラクター + デストラクター呼び出しの 2 つだけです。この点に関する実行例については、この投稿を参照してください。
このような変数が多数存在する実際のアプリケーションでは、この代入ペナルティはさらに大きくなります。おかげで ptr この点を追加するために。
C++ におけるパラメータと均一な初期化
変換の縮小や予期しない動作の問題を回避するには、パラメーターの初期化 () ではなく、均一な初期化 {} を含む初期化リストを使用することをお勧めします。初期化中により厳密な型チェックを提供し、潜在的な縮小変換を防止します。
パラメータの初期化を使用したコード ()
C++
#include> class> Base {> >char> x;> public>:> >Base(>char> a)> >: x{ a }> >{> >}> >void> print() { std::cout <<>static_cast><>int>>(バツ); }>> };> int> main()> {> >Base b{ 300 };>// Using uniform initialization with {}> >b.print();> >return> 0;> }> |
>
>出力
44>
上記のコードでは、値 300 は char の有効範囲外であるため、未定義の動作が発生し、誤った結果が生じる可能性があります。コンパイラは、コンパイル設定に応じて、この状況に対して警告またはエラーを生成する場合があります。
均一初期化を使用したコード {}
{} による均一な初期化を使用し、指定された値 a で x を初期化することにより、コンパイラーはより厳密な型チェックを実行し、コンパイル中に警告またはエラーを発行して、int から char への縮小変換を示します。
これは均一な初期化 {} を使用したコードです。これにより警告が発生するため、使用することをお勧めします。
C++
#include> class> Base {> >char> x;> public>:> >Base(>char> a)> >: x{ a }> >{> >}> >void> print() { std::cout <<>static_cast><>int>>(バツ); }>> };> int> main()> {> >Base b{ 300 };>// Using uniform initialization with {}> >b.print();> >return> 0;> }> |
>
>
main.cpp: In function ‘int main()’: main.cpp:17:17: error: narrowing conversion of ‘300’ from ‘int’ to ‘char’ [-Wnarrowing] 17 | Base b{ 300 }; // Using uniform initialization with {} | ^>