2016-03-23 8 views
8

私は、関数内のローカル変数が別の関数内で同じ名前のローカル変数に渡されているC++の学習で問題が発生しました。 ()。ローカル変数が渡されました(C++)

これが実行され、

#include <iostream> 
using namespace std; 

void next(); 
void again(); 

int main() 
{ 
    int a = 2; 
    cout << a << endl; 
    next(); 
    again(); 
    return 0; 
} 

void next() 
{ 
    int a = 5; 
    cout << a << endl; 
} 

void again() 
{ 
    int a; 
    cout << a << endl; 
} 

それは出力:

2 
5 
5 

私は '' 再びそこに宣言し、そしてまだそれはそうしているので、再び()がnullまたは0と言うだろうと予想next()に 'a'が代入された値を使用します。

なぜ、 'a'がもう一度again()で宣言された場合、next()はローカル変数 'a'の値をagain()に渡しますか?

+3

何も渡されませんでした。 'again()'の 'a'は初期化されていませんでした。 – songyuanyao

+0

合意されているので、 'a'の値は未定義の振る舞いです。 – drescherjm

答えて

7

http://en.cppreference.com/w/cpp/language/ub

あなたは正しいです、初期化されていない変数には、noです。ただし、変数を宣言して後で初期化することはできません。メモリは整数を保持するために確保されていますが、その値が何かになるまで、その値はそのメモリに格納されます。コンパイラの中には、(バグを捕捉するのに役立つように)変数をジャンク値に自動初期化するものと、デフォルト値に自動初期化するものと、まったく何もしないものがあります。 C++自体は何も約束しないので、未定義の動作です。あなたの場合、単純なプログラムでは、コンパイラが同じメモリを変更せずに再利用したアセンブリコードをどのように作成したのか想像するのは簡単です。しかし、それは盲目であり、あなたの単純なプログラムでさえ、起こることが保証されていません。これらのタイプのバグは実際には非常に狡猾である可能性があるので、ルールにしてください:初期化されていない変数について注意してください。

1

これは完全に偶然であり、未定義の動作です。

何が起こったかは、直ちに呼び出される2つの関数があることです。両方とも多かれ少なかれ同一の関数プロローグを持ち、両方ともスタックにまったく同じサイズの変数を予約します。

コールの間に他の変数はなく、スタックは変更されていないので、2番目の関数 "landing"のローカル変数は、前の関数のローカル変数と同じ場所に終わることがあります。

明らかに、これは信頼できません。実際には、それはなぜあなたがの変数を初期化する必要があるの完全な例です!

5

*ビルトインタイプ(あー!それだった一口)の初期化されていない非staticローカル変数は、不定値を持っています。 charタイプを除いて、その値を使用すると正式に未定義動作、a.k.a. UBが生成されます。あなたが見る行動を含め、何かが起こる可能性があります。今とどうやらあなたのコンパイラとオプション、nextの呼び出しでaのために使用されたスタック領域と、それはagainaのために再利用されたagainのコールまで、何か他のもののために使用されなかった

前と同じ値。

しかし、あなたはそれに頼ることはできません。 UBと何か、あるいは何も起こりません。


*以上の一般POD型の、平原古いデータ。この規格の仕様はやや複雑です。 C++ 11では、§8.5/ 11で始まります。「オブジェクトにイニシャライザが指定されていない場合、オブジェクトはデフォルトで初期化されます。初期化が実行されない場合、自動または動的記憶期間を持つオブジェクトは不確定な値を持ちます。 "どこで "自動&hellip; 「記憶期間」には、ローカル非static変数の場合が含まれます。デフォルト初期化を定義する§8.5/ 6を介して、つまり、何もしないデフォルトのコンストラクタを介して、またはクラスまたは配列型でないオブジェクトを介して、「初期化なし」が2つの方法で発生する可能性があります。

関連する問題