次のコードでは、変数に初期値がなく、この変数を出力しました。
int var;
cout << var << endl;
出力: 2514932
double var;
cout << var << endl;
出力: 1.23769e-307
これらの出力数値がわかりません。誰でもこれを説明できますか?
次のコードでは、変数に初期値がなく、この変数を出力しました。
int var;
cout << var << endl;
出力: 2514932
double var;
cout << var << endl;
出力: 1.23769e-307
これらの出力数値がわかりません。誰でもこれを説明できますか?
簡単に言えば、var
は初期化されておらず、初期化されていない変数を読み取ると未定義の動作が発生します。
だからやらないでください。あなたがした瞬間、あなたのプログラムはあなたが言ったことを何も保証しなくなります。
正式には、値を「読み取る」とは、左辺値から右辺値への変換を実行することを意味します。そして§4.1は、「...オブジェクトが初期化されていない場合、この変換を必要とするプログラムには未定義の動作があります」と述べています。
実用的には、これは単に値がガベージであることを意味します (結局のところ、 を読み取るのは簡単にわかりますint
。たとえば、ランダムなビットを取得するだけです) が、これを結論付けることはできません。
実際の例として、次のことを考慮してください。
#include <iostream>
const char* test()
{
bool b; // uninitialized
switch (b) // undefined behavior!
{
case false:
return "false"; // garbage was zero (zero is false)
case true:
return "true"; // garbage was non-zero (non-zero is true)
default:
return "impossible"; // options are exhausted, this must be impossible...
}
}
int main()
{
std::cout << test() << std::endl;
}
単純に、(コメントの推論を介して) これは決して印刷されるべきではないと結論付けるでしょう"impossible"
。しかし、未定義の動作では、何でも可能です。でコンパイルしg++ -02
ます。
あなたがするとき:
int var;
という名前の整数のみを宣言していvar
ます。値で初期化しないため、どこにいてvar
もガベージ データになります。
int var = 5;
var を宣言し、5 に初期化します。
あなたが得ているのは、コンパイラが変数を整数または倍精度浮動小数点数として解釈する必要があると判断した場所のスタック上にたまたまあったデータです。プログラムは一般に決定論的に動作するため、プログラムを実行するたびに同じになる可能性があります。プログラムの実行ごとに同じではない場合も多くありますが。プログラムを少し変更したり、そのコードに到達する前にユーザー入力に基づいて決定を下したりすると、異なる数値が得られる場合と得られない場合があります。
基本的に、初期化していない変数の値は指定されておらず、絶対に何でもかまいません。そこに韻や理由はありません。初期化されていない変数を使用することは、(正式に言えば) 未定義の動作であり、あらゆる種類の奇妙な結果になる可能性があります。
これを行うことは一般的に悪い習慣です。予測可能な方法で動作するプログラムが必要であり、変数が初期化されていないことは予測不能の原因です。これはランダム性の原因ではなく、単に予測不可能であることに注意してください。すべての警告をオンにすると、ほとんどのコンパイラはそのようなコードについて文句を言います。
C++ では、変数を宣言すると、コンパイラによってメモリ アドレスが変数に割り当てられます。それだけです。クリーンアップは行われません。これは主に、C++ (および C) がパフォーマンスを考慮して構築されているためです。C++ は、明示的に指定しない限り、アドレスの初期化に時間を費やしません。
そして、あなたが目にするいわゆるガベージは、それを使用した最後の変数によってそのアドレスに残されたものです。
他の言語では、データが初期化されます。実際、C# では、初期化するまで変数を使用できません。これらの言語は、初期化されていないアドレスを誤って使用してプログラムをクラッシュさせたり、さらに悪いことにデータを破損させたりするようなコードを記述できないという意味で、安全になるように設計されています。
var
どちらの場合も初期化しなかったため、ガベージ出力が得られます。
やった?
const int var(5);
値で初期化されます5
varを宣言すると、メモリ内の場所が割り当てられます。ただし、そのメモリはデフォルトでは何も設定されていないため、以前にあったものは何でも取得します。これは、意味のないガベージ値になります。
C++ では、これはメンバー変数とローカル変数の両方に当てはまります。ただし、Java や C# などの言語では、メンバー変数は数値型の場合は 0 に、ブール値の場合は false に、参照の場合は null に自動的に初期化されます。これはローカル変数に対しては行われず、(少なくとも C# コンパイラでは) 初期化されていない変数の値を取得しようとすると、ビルドは失敗します。