你體驗被稱爲返回值優化什麼(見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+
創建的臨時對象是一樣的a
(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+
創建一個本地對象(0x7ffd92847cff
),這是後來複製的臨時對象return語句(複製0x7ffd92847cff
到0x7ffd92847d1f
),最後將其用於構建通過複製(複製0x7ffd92847d1f
至0x7ffd92847d1e
)。
'MyClass&operator =(const MyClass&cls)' - 此函數調用未定義的行爲,因爲您未能返回值。 – PaulMcKenzie
對不起,我的錯誤。我糾正了它。但我認爲這個問題不是嚴重的誤導。 – AK2806
它是嚴重的,它在程序的工作方式中扮演着重要角色。沒有回報價值,任何事情都可能發生。 – PaulMcKenzie