あなたが言及した引用は、関数から参照を返し、その参照を一時的にバインドするためのものです。
const T& f() { return T(); };
returnステートメントではなく、呼び出し側で一時を参照にバインドしているため、コードではそうではありません。コメントでは、コードを次のように変更すると次のようになります。
T f() { return T(); }
T&& r = f();
寿命はまだ延長されていますが、それは間違っています。return
一時的なものは、返された値にコピーされるステートメントの期間中存続します。コピーが完了すると、一時的な有効期間が終了します。f()
呼び出し側では、存続期間が延長される別の一時 ( の結果) があります。
しかし、テンポラリーの寿命が延びていることは間違いありません。クラス A のデストラクタを任意のメッセージで定義すると、それは main() の最後に出力されますか、それともありますか?
その発言も間違っています。戻り値の最適化 (RVO) の効果が見られます。T()
関数内の一時オブジェクトと戻り値用の一時オブジェクトを作成する代わりに、コンパイラは同じ場所に 2 つのオブジェクトを作成しています。プログラムの出力にはおそらく 1 つのオブジェクトが表示されますが、理論的には 2 つのオブジェクトがあります。
-fno-elide-constructors を指定して g++ を使用すると、両方の一時オブジェクトが表示されるはずです。一方が拡張され、もう一方が拡張されません。
または、参照を返すこともできます。
const A& f() { return A(); }
const A& r = f();
r
範囲外になる前に一時的に終了する方法を示す必要があります。
これは基本的に、
$ g++ --バージョン | 頭-1
g++ (GCC) 4.3.2
$ 猫 x.cpp
#include <iostream>
struct X {
X() { std::cout << "X\n"; }
~X() { std::cout << "~X\n"; }
};
X f() { return X(); }
int main() {
const X& x = f();
std::cout << "still in main()\n";
}
$ g++ -o t1 x.cpp && ./t1
X
still in main()
~X
$ g++ -fno-elide-constructors -o t2 x.cpp && ./t2
X
~X
still in main()
~X
$ clang++ -バージョン | 頭-1
$ clang バージョン 3.2 (タグ/RELEASE_32/final)
$ clang++ -fno-elide-constructors -o t3 x.cpp && ./t3
X
~X
still in main()
~X
$猫y.cpp
#include <iostream>
struct X {
X() { std::cout << "X\n"; }
~X() { std::cout << "~X\n"; }
};
const X& f() { return X(); }
int main() {
const X& x = f();
std::cout << "still in main()\n";
}
$ g++ -fno-elide-constructors -o t4 y.cpp && ./t4
X
~X
still in main()