2016-04-17 12 views
0

私は次のコードを持っている:私はそれを実行するとC++のコンストラクタ/デストラクタ

#include <iostream> 

using namespace std; 

class A 
{ 
public: 
    A() 
    { 
     cout<<"cons"<<endl; 
    } 
    ~A() 
    { 
     cout<<"dest"<<endl; 
    } 
}; 

A 
gokul (void) 
{ 
    A p; 

    return p; 
} 

int 
main() 
{ 
    A a = gokul(); 
    cout<<"done\n"; 
} 

を。

短所私は出力があることを期待していた

destの

行わ

:私は次の出力を取得 - > P作成し、

両論

短所を - - >ゴールを返すために

dest - > p destroとき、関数gokul戻り、新しい変数>破壊され、メインはローカル変数として

を返さ「p」が「」になり破壊される - YED、gokulは

DESTを行って

を返さ作成された、いいえ?私はすべての3つのスタンダード03、11 & 14でコンパイルしましたが、同じ結果が得られます。 〜

+3

http://en.cppreference。com/w/cpp/language/copy_elision – jtbandes

+2

コピーコンストラクタをトレースしませんでした。オブジェクトはデフォルトで構築されるだけでなく、コピー構築されます。 – PaulMcKenzie

+0

@PaulMcKenzieコピーコンストラクタに "copy"を追加しても出力は変更されません。 – xinaiz

答えて

5

コードがコピーコンストラクタのトレースに失敗しました。オブジェクトをいつ作成するのかをよりよく把握するには、これを行う必要があります。

#include <iostream> 
using namespace std; 

class A 
{ 
public: 
    A() { cout<<"cons"<<endl; } 
    ~A() { cout<<"dest"<<endl; } 
    A(const &A) { cout << "copy constructed" << endl;} 
}; 

A gokul (void) 
{ 
    A p; 
    return p; 
} 

int main() 
{ 
    A a = gokul(); 
    cout<<"done\n"; 
} 

あなたは、Visual Studio 2015、なしの最適化にこのコードを実行すると、以下のように、出力は次のとおりです。

cons 
copy constructed 
dest 
done 
dest 

あなたはモードを解除するために変更すると、出力は今、このです:

cons 
done 
dest 

2番目の出力がコピーを作成しない理由は、コピーを削除するために行われたNamed Return Value Optimizationが原因です。

ただし、コピーコンストラクタの呼び出し回数を実際に予測できないという点があります。ご覧のとおり、最適化されていないバージョンも正しく動作します。

+0

ありがとう@PaulMcKenzie。それは良い洞察でした!不思議なことに、私は最適化を無効にした後でも最適化された出力を得ています。 g ++ -O0 test.cpp – soupybionics

+1

まあ、述べたように、あなたは本当にこれらのことを前もって予測することはできません。 「このコードでコピーコンストラクタが何回呼び出されているか」という質問を得るたびに、それはトリック質問です。 – PaulMcKenzie

+0

@soupybionics - はい、この「最適化」は、g ++が '-O0'レベルでもそれを実行することが分かります。あなたが本当に大きくて遅いバージョンを生成したいのであれば、 '-fno-elide-constructors'を使って、そうしないように特別に要求しなければなりません。 –

0

あなたは、最適化は、あなたので、コンパイラの最適化のこの出力を得るCopy Elisionenter link description here

それとも、(最適化なし)デバッグモードでプログラムを実行した場合、あなたは、単にコピーコンストラクタをトレースしていないをオンにしている場合@PaulMcKenzieが説明したように使用されます。

/Od(ビジュアルスタジオで)-O0 gccでコンパイルできます。または、デバッグモードで実行します。そして、/O2または-O2で最適化バージョンに戻ります。

非最適化バージョン/0dにswithしても、出力が得られない場合、C++ 11コンパイラは移動コンストラクタを使用できることに注意してください。したがって、移動コンストラクタをトレースする必要があります

A(const A&& o){ 
    cout << "move ctor" << endl; 
} 
+0

OPの最適化がオンになっているかどうかOPが投稿した元のコードには、コピーコンストラクタがトレースされていないので、挿入された場合の出力の内容はわかりません。 – PaulMcKenzie

+0

はい、良い点 – userbb