2016-11-20 7 views
0

私はMyClass a = bのような式がコピー初期化であることを知っていて、コピーコンストラクタを呼び出します。式MyClass a = b + cはコピーの初期化ですか?

MyClassはどうですか?a = b + c?

私はそれを試しました。ビジュアルスタジオ2015では、表現はコピー初期化やコピー割り当てではないようです。それは何ですか?以下は

は、私がテストしたコードです:

class MyClass 
{ 
public: 
    MyClass() 
    { 
     cout << "default constructor has been called!" << endl; 
    } 
    MyClass(const MyClass& cls) 
    { 
     cout << "copy constructor has been called!" << endl; 
    } 
    MyClass operator+(const MyClass& cls) const 
    { 
     cout << "operator + has been called!" << endl; 
     return MyClass(); 
    } 
    MyClass& operator=(const MyClass& cls) 
    { 
     cout << "operator = has been called!" << endl; 
     return *this; 
    } 
}; 

int main() 
{ 
    MyClass b, c; 
    MyClass a = b + c; 
    return 0; 
} 

、出力は

default constructor has been called! 
default constructor has been called! 
operator + has been called! 
default constructor has been called! 
+0

'MyClass&operator =(const MyClass&cls)' - この関数は、値を返さなかったため未定義の動作を呼び出します。 – PaulMcKenzie

+0

私の間違い申し訳ありません。私はそれを修正しました。しかし、私はこの質問で深刻な誤解を招くとは思わない。 – AK2806

+0

プログラムがどのように機能するかは、それが重要なことです。戻り値はなく、何かが起こる可能性があります。 – PaulMcKenzie

答えて

0

あなたは、戻り値の最適化と呼ばれる体験(What are copy elision and return value optimization?を参照してください)。

コンパイラはコードを最適化し(オブジェクトの作成を最小限に抑えるため)、オペレータによって宣言され返されたローカルオブジェクトをaにします。次に、コピーコンストラクタは使用されません。これはあなたがここで観察するものです。うまくオブジェクトのメモリは住所が見るためにあなたのコードを変更し、これを観察する

#include <iostream> 
using namespace std; 

class MyClass 
{ 
public: 
    MyClass() 
    { 
     cout << "default constructor has been called for " << std::hex << this << endl; 
    } 
    MyClass(const MyClass& cls) 
    { 
     cout << "copy constructor has been called for " << std::hex << this << " (copied from " << &cls << ")" << endl; 
    } 
    MyClass operator+(const MyClass& cls) const 
    { 
     cout << "operator + has been called!" << endl; 
     MyClass res; 
     cout << "operator + returns temporary object " << std::hex << &res << endl; 
     return res; 
    } 
    MyClass& operator=(const MyClass& cls) 
    { 
     cout << "operator = has been called!" << endl; 
     return *this; 
    } 
}; 

int main() 
{ 
    MyClass b, c; 
    MyClass a = b + c; 
    cout << "a object is " << std::hex << &a << endl; 
    return 0; 
} 

それは出力:

あなたは operator+で作成した一時オブジェクトは a0x7ffd44b769ffと同じであることがわかり
default constructor has been called for 0x7ffd44b769fd 
default constructor has been called for 0x7ffd44b769fe 
operator + has been called! 
default constructor has been called for 0x7ffd44b769ff 
operator + returns temporary object 0x7ffd44b769ff 
a object is 0x7ffd44b769ff 

を)、コンパイラの最適化のためです。

g ++を使用する場合、このコンパイラの最適化を無効にするには、-fno-elide-constructorsでコンパイルしてください。そして、出力は以下のようになります。

default constructor has been called for 0x7ffd92847d1c 
default constructor has been called for 0x7ffd92847d1d 
operator + has been called! 
default constructor has been called for 0x7ffd92847cff 
operator + returns temporary object 0x7ffd92847cff 
copy constructor has been called for 0x7ffd92847d1f (copied from 0x7ffd92847cff) 
copy constructor has been called for 0x7ffd92847d1e (copied from 0x7ffd92847d1f) 
a object is 0x7ffd92847d1e 

あなたは今operator+は最終的に構築するために使用された後に、return文のための一時的なオブジェクトとしてコピーされるローカルオブジェクト(0x7ffd92847cff)、(0x7ffd92847d1fから0x7ffd92847cffをコピー)を作成していることがわかりaコピー(コピー0x7ffd92847d1f0x7ffd92847d1e)。

2

このような場合のコピーコンストラクタmay be elidedです。 operator+は右辺値MyClassのを返すので、Cからの

2

++型perslective、

MyClass a = b + c; 

MyClass a = MyClass(); 

間には違いがありません。 aのオブジェクトを作成したばかりなので、そのオブジェクトを直接 aに作成するだけです。

この

は、ここでは最初の例で説明されています http://en.cppreference.com/w/cpp/language/copy_elision

関連する問題