你体验被称为返回值优化什么(见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