C++ネーミング戻り値最適化

2254 ワード

C++の次の3つのオブジェクトでコピーコンストラクション関数を呼び出す必要があります.
1.オブジェクトが値伝達で関数パラメータに入力
2.オブジェクトは値伝達で関数から返される
3.オブジェクトを別のオブジェクトで初期化する必要がある
class A
{
    public:
        A(){cout<

最初は、このプログラムは少なくとも2回のコンストラクション関数を呼び出して2つのオブジェクトを生成する必要があると思います.
fun: A a;
main: A a=fun();
疑問なのはfunがaを返すときに、戻り値オブジェクトを構築するかどうかです.
G++4.4でコンパイル、g++testReturn.cpp
実行、印刷結果:
in main
in fun
constructor
returning fun
returning main
destructor
一度だけコンストラクション関数を呼び出すなんて!!!
コンストラクション関数はfunで呼び出され、コンストラクション関数はmainで呼び出されます.
明らかに、g++は、mainで新しいオブジェクトを構築することなくfun()の戻りオブジェクトをコンパイル最適化して直接使用する.
しかし、もし私が関数を構築する上で重要なことがあったら、例えばnewのオブジェクトが必要だとか、どうすればいいのでしょうか.
g++のコンパイル最適化オプションを削除しますか?g++ -O0 testReturn.cpp
得る
結果は次のとおりです.
in main
in fun
constructor
returning fun
returning main
destructor
Googleでは、これは名前付き戻り値最適化という問題であり、g++のこのコンパイル最適化には直接的な閉じる方法がないことに気づき、163ブログで関連する手がかりを見て、言及した.
Joe Buck  writes:

> On Wed, Nov 07, 2007 at 07:48:53AM -0800, Ian Lance Taylor wrote:
> > "Debarshi Sanyal"  writes:
> > 
> > > Is there any way to turn off "named return value optimization"
> > > (NRVO) while compiling a C++ program with g++?
> > 
> > This question is not appropriate for [email protected], which is for
> > developers of gcc. It is appropriate for [email protected].
> > Please take any followups to that mailing list. Thanks.
> > 
> > The answer to your question is no. g++ will always implement NRVO
> > when possible.
> 
> You forgot about -fno-elide-constructors , Ian. I've needed it in
> the past to work around a bug in profiling; there's a PR for this.

Ah, tricky. Thanks.

Ian

試してみました、g++
 -fno-elide-constructors testReturn.cpp、実行結果:
in main
in fun
constructor
returning fun
copy constructor
destructor
copy constructor
destructor
returning main
destructor
やっとmainのコピー構造関数が見えました!
ただしfunが返す場合、プログラムは戻り値オブジェクトを1つも構築していないため、コンストラクション関数は2回しか呼び出されません.
vs 2017ではコンパイラのデフォルトではネーミングの最適化は行われません