D
の別の部分に基づいて の一部を初期化する次のコードを検討してくださいD
。
struct c {
c() : D{rand(), D[0]} {}
int D[2];
};
int main() {
c C;
assert(C.D[0] == C.D[1]);
}
上記のプログラムは適切に定義されていますか? 同じ配列の一部を安全に使用して、別の部分を初期化できますか?
D
の別の部分に基づいて の一部を初期化する次のコードを検討してくださいD
。
struct c {
c() : D{rand(), D[0]} {}
int D[2];
};
int main() {
c C;
assert(C.D[0] == C.D[1]);
}
上記のプログラムは適切に定義されていますか? 同じ配列の一部を安全に使用して、別の部分を初期化できますか?
配列メンバーを自己参照で初期化できますか?
はい。
struct c {
int a[3];
c() : a{4, a[0], 3} {} // a[0] is initialized to 4.
// a[1] is initialized to whatever a[0] is. (4)
// a[2] is initialized to 3.
};
しかし、次の例を考えてみましょう:
struct c {
int a[3];
c() : a{a[1], 4, a[1]} {} // a[0] is initialized to whatever a[1] is.(Garbage value)
// a[1] is initialized to 4.
// a[2] is initialized to what a[1] is now (4).
};
ここで、 の最初の要素は のa
値でありa[1]
、おそらくガベージ値です。2 番目の要素は に初期化され4
、3 番目の要素は現在a[1]
の値である に初期化されます4
。
また、 内の配列内のすべての要素をリストしない場合、リスト{}
されていない要素はデフォルトで初期化されます。
struct c {
int a[5]; // notice the size
c() : a{a[1], 2, 3, 4}{} // a[0] will get value that is in a[1]
// but since a[1] has garbage value,
// it will be default initialized to 0.
// a[1] = 2
// a[2] = 3
// a[3] = 4
// a[4] is not listed and will get 0.
};
ただし、すでに初期化されている要素をリストすると、必要な値が得られます。
上記の例を使用します。
struct c {
int a[5];
c() : a{1, a[0], 3, 4}{} // a[0] = 1
// a[1] = 1
// a[2] = 3
// a[3] = 4
// a[4] is not listed and will get 0.
};
コンストラクターが実行されるときに、最初に rand() が実行され、次に D[0] が実行される必要はないため、を記述することはお勧めでき
D{rand(),D[0]}
ません。すべてはコンパイラーに依存し、D[0] を最初に実行することができます。その場合、d[1] にはガベージ値が含まれます。これは完全にコンパイラに依存します。最初に 2 番目の引数をコンパイルしてから最初の引数をコンパイルするか、またはその逆を行うことができます。このステートメントを実行すると、未知の動作が発生する可能性があります。