以前のものを新しいもの101
に割り当てているときに出力されないのはなぜですか?x
x
int x = 101;
{
int x = x;
std::cout << x << std::endl;
}
出力 (ガベージ):
422634
x
2番目は初期化されると思いましたが、初期化され101
ていません。
注: この場合の解決策は次のとおりですint x = ::x
が、問題はなぜそれが起こるのかです。
以前のものを新しいもの101
に割り当てているときに出力されないのはなぜですか?x
x
int x = 101;
{
int x = x;
std::cout << x << std::endl;
}
出力 (ガベージ):
422634
x
2番目は初期化されると思いましたが、初期化され101
ていません。
注: この場合の解決策は次のとおりですint x = ::x
が、問題はなぜそれが起こるのかです。
名前の宣言のポイントは、完全な宣言子の直後と初期化子の前です... [C++ 標準 § 3.3.2/1]
コンパイラは、宣言子について十分に認識している場合、宣言を完了します。
上記のコードは以下のコードと同じです:
int x = 101;
{
int x;
x = x; <------------------// Self assignment, assigns an indeterminate value.
std::cout << x << std::endl;
}
なぜなら、 (代入)の前に内部の宣言がx
完了しているからです。=
int x = x; <--// Now, we have the new `x` which hides the older one,
^ // so it assigns itself to itself
|
+---// Point of declaration,
// here compiler knows everything to declare `x`.
// then declares it.
一方、複雑なオブジェクトを宣言するときは、宣言のポイントが遠くなります。したがって、動作が異なります。
たとえば、以下のコードは問題ありません
const int i = 2;
{
int i[i];
^
|
+----// Point of declaration
// compiler has to reach to "]"
// therefore before declaring `i` as an array
// there is just one `i`, the `i` of `const int i=2`
}
上記のコードでは、コンパイラは宣言を完了するために配列の実際のサイズを知る必要があるため、宣言のポイントは です]
。したがって、ofの宣言がまだ完了していないため、insideはouteri
です。したがって、要素を持つ配列を宣言します ( )。[i]
i
i
int i[...
2
int i[2];
また、この例は、列挙子の宣言のポイントを示しています
const int x = 12;
{
enum { x = x };
^
|
+---// Point of declaration
// compiler has to reach to "}" then
// there is just one `x`, the `x` of `const int x=12`
}
列挙子x
は、定数の値x
、つまりで初期化されます12
。
変数のスコープ x の前は上書きされます。int x = x; これには2つのプロセスがあります。1: int x;(変数 x を定義してメモリを割り当て、初期値を指定: x = 0); この瞬間、前面の x が隠れます。2: x = x;(値 x が見つからない);