0

TDM-GCC 4.6.1 コンパイラを使用して右辺値参照について実験を行ったところ、理論では説明できない興味深い観察結果が得られました。専門家に説明を手伝ってもらいたいです。

オブジェクトではなく int プリミティブを処理し、foo1 (右辺値参照によってローカル変数を返す) と foo2 (値によってローカル変数を返す) の 2 つの関数を定義した非常に単純なプログラムがあります。

#include <iostream>

using namespace std;

int &&foo1();
int foo2();

int main()
{

int&& variable1 = foo1();
//cout << "My name is softwarelover." << endl;
cout << "variable1 is: " << variable1 << endl; // Prints 5.
cout << "variable1 is: " << variable1 << endl; // Prints 0.

int&& variable2 = foo2();
cout << "variable2 is: " << variable2 << endl; // Prints 5.
cout << "variable2 is still: " << variable2 << endl; // Still prints 5!

return 0;
}

int &&foo1() {

int a = 5;
return static_cast<int&&>(a);
}

int foo2() {

int a = 5;
return a;
}

foo1 によって返され、variable1 によって受信された値は、しばらくすると消滅するようです。おそらく、数ミリ秒の短い期間です。コメントアウトすることで、cout が「My name is softwarelover」と出力しないようにしていることに注意してください。そのステートメントの実行を許可すると、結果は異なります。5, 0 を出力する代わりに、0, 0 を出力します。5 が 0 に変わるのは、"cout << "My name is softwarelover." によって導入された時間遅延が原因のようです。

上記は、関数が値渡しではなく参照によって返されたプリミティブ整数を参照するときに、右辺値参照がどのように動作することになっているのでしょうか? ところで、なぜ0なのか、ゴミではないのか。

variable2 は、c で何度印刷しても消えないように見えることにも注意してください! variable2 は、関数が参照渡しではなく値で返すプリミティブ整数を参照します。

ありがとう。

4

1 に答える 1

5

右辺値参照はまだ単なる参照です。関数が戻った後、関数のローカル変数への参照は無効です。幸運なことに、関数が戻った後は技術的に無効であるため、関数呼び出し後はいつでも右辺値の参照が5になります。

編集:私は私の答えを拡張しており、一部の人々がいくつかの追加の詳細が役立つことを期待しています。

関数内で定義された変数は、関数ローカル変数です。その変数の有効期間は、宣言された関数の内部に制限されます。関数が戻ったときに「破棄」されたと考えることができますが、実際には破棄されません。オブジェクトの場合、そのデストラクタが呼び出されますが、変数を保持していたメモリはまだそこにあります。その変数への参照またはポインタは、メモリ内の同じ場所を指しますが、そのメモリは再利用されています(または、将来の不確定な時点で再利用される可能性があります)。

古い値(あなたの場合は「5」)は、何かがやって来てそれを上書きするまで、しばらくの間そこにあります。値がまだ存在する期間を知る方法はありません。また、関数が戻った後も、値がまだ存在していることに依存することはできません。関数が戻ったら、関数のローカル変数への参照(またはポインター)は無効であると考えてください。比喩的に言えば、ドアをノックしに行くと、おそらく新しいテナントは納得がいかないでしょう。

于 2012-09-04T16:45:44.453 に答える