以下のコードは、コンパイラによって出力された警告と、関数内のA
オブジェクトのデストラクタg()
が関数が戻る前に呼び出されるという事実に見られるように、ダングリング参照を生成します。「スタックを使用」した後、返された参照にガベージがあることを確認することもできmain()
ます (少なくともデバッグ ビルドでは)。しかし、リリース ビルドでは同じ動作を再現できませんでした。何故ですか?r
参照が OKであるという印象を与えるために、コンパイラはここでどのような最適化を行っているのでしょうか?
#include <iostream>
struct A{
A(int i) : i(i) { std::cout << "Ctor\n"; }
A(const A& a) { i = a.i; std::cout << "Copy ctor\n"; }
~A() { std::cout << "Dtor\n"; }
int i;
};
A& g(int i) { A x(i); return x; }
int main()
{
const A& r = g(1);
std::cout << "Using the stack\n";
std::cout << r.i << '\n'; // r.i has garbage in debug, but not in a release build.
}
PS。関数はオブジェクトを返さないため、NRVO には反対しA
ます。
編集:マーク・トロネンへの返信。リリースビルド後にこれらの式を含めても、const A& r = g(1);
ゴミは表示されませんstd::cout << r.i << '\n';
std::cout << "Using the stack ...................................................................................................................\n";
std::cout << "Using the stack ...................................................................................................................\n";
std::cout << "Using the stack ...................................................................................................................\n";
std::cout << "Using the stack ...................................................................................................................\n";