2017-07-28 1 views
1

私はまだC++には新しく、オブジェクトスコープを研究しています。
私は下のコードをテストし、いくつかの奇妙な動作を目撃しました。オブジェクトが有効範囲外になるべきときにこのポインタが有効なのはなぜですか? (そして、他の奇妙な振る舞い)

struct Test 
{ 
    int value, value2; 
    Test() : value(1), value2(10) {}; 
}; 


Test* GetTestPointer() { 
    Test t; 
    t.value = 20; 
    return &t; 
} 

int main() { 
    Test* tp = GetTestPointer(); 
    int a = tp->value; 
    int b = tp->value2; 
    cout << a << endl; 
    cout << b << endl; 

    return 0; 
} 

は出力:

20 
10 

私は例外または空の値を投げるだろうどちらかTest tはとてもメインでその値を逆参照範囲の外に行くだろうと思いました。あたかもオブジェクトがまだ生存しているかのように有効な値を取得するのはなぜですか?

は、実はこれは私が最初に試したものです:

Test* tp = GetTestPointer(); 
cout << tp->value << endl; 
cout << tp->value2 << endl; 

出力:それは無効だが、私はvalueうまく得ることができるようにここで

20 
18223279 

value2が作用しています。
逆に、私はそれらを並べ替えてみました:

Test* tp = GetTestPointer(); 
cout << tp->value2 << endl; 
cout << tp->value << endl; 

出力:予想通り、私は正しく、newtpを開始したとき、これのどれも起こらなかったことを

10 
1459403656 

注意。

私は実際にこのようなコードを書くことは決してないと知っていますが、なぜこれが起こっているのか本当に不思議です。

  1. この場合、tはどのようなときに範囲外になりますか?
  2. coutの注文は、tpが参照しているものと何が関係していますか?
  3. バッファに保存すると、正しい値を取得できますか?
+1

あなたは幸運でした。これは未定義の動作です。 – tilz0R

+0

_このポインタは有効ですか?そうではありません。未定義の動作は未定義です。 –

+0

「空の」値はどのように見えますか? – molbdnilo

答えて

2

あなたは正しい値であることが幸運が、一般的に、それは未定義の動作であり、あなたのコンパイラはこれについて警告を表示しなければなりません。

はこのような何かにあなたの例を拡張してください:

int my_sum(int a, int b) {return a + b;} 
int main() { 
    int res; 
    Test* tp = GetTestPointer(); 
    res = my_sum(1, 2); 
    int a = tp->value; 
    int b = tp->value2; 
    cout << a << endl; 
    cout << b << endl; 

    return 0; 
} 

お近くのスコープTestオブジェクトが別の関数呼び出しによって上書きされたため、あなたは異なる出力が表示されます。

newステートメントを使用すると、オブジェクトはローカルではなくHEAPメモリ上に作成されるため、機能範囲外に出るときに有効になります。この場合、後でこのオブジェクトを削除するにはdeleteを使用する必要があります。

+0

もっと不運にも似ていると思います。私は一時的なアドレスを返すという警告を受けましたが、それ以外の場合はコンパイルされ、中断することなく正常に実行されました。未定義の振る舞いは常にこのように気付かれませんか?たとえばゼロで割ると私のプログラムは終了します。 – LinguistTroubadour

+0

将来あなたのプログラムが失敗するかもしれないのであなたは不運でした:)しかし、一般的に未定義の動作はあなたの実行を簡単にクラッシュさせる可能性があります:) @LinguistTroubadour – tilz0R

関連する問題