2016-11-20 59 views
0

我知道表達式像MyClass a = b是一個複製初始化,它會調用複製構造函數。表達式MyClass a = b + c是一個拷貝初始化嗎?

MyClass a = b + c呢?

我試過了。在Visual Studio 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; 
} 

它輸出:

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 

你看,在operator+創建的臨時對象是一樣的a0x7ffd44b769ff ),由於編譯器的優化。

如果使用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+創建一個本地對象(0x7ffd92847cff),這是後來複製的臨時對象return語句(複製0x7ffd92847cff0x7ffd92847d1f),最後將其用於構建通過複製(複製0x7ffd92847d1f0x7ffd92847d1e)。

相關問題