问题
I run this code for experimenting copy constructor and assignment operator
class AClass {
private:
int a;
public:
AClass (int a_) : a(a_) {
cout << " constructor AClass(int) " << a << endl;
}
AClass(const AClass & x) : a(x.a) {
cout << " copy constructor AClass(const AClass &) " << a << endl;
}
AClass & operator=(const AClass & x) {
a = x.a;
cout << " AClass& operator=(const AClass &) " << a - endl;
return *this;
}
};
AClass g () {
AClass x(8);
return x;
}
int main () {
cout << " before AClass b = g() " << endl;
AClass b = g();
cout << " after" << endl;
cout << " before AClass c(g()) " << endl;
AClass c (g());
cout << " after" << endl;
}
and found that no message appears for the return x;
Why?
Should not the copy constructor or operator= be called?
This is the output:
before AClass b = g() constructor AClass(int) 8 after before AClass c(g()) constructor AClass(int) 8 after
回答1:
The compiler is allowed to elide copying in a case like this. This is called Return Value Optimization.
回答2:
In C++, the compiler is allowed to remove calls to the copy constructor in almost all circumstances, even if the copy constructor has side effects such as printing out a message. As a corollary, it is also allowed to insert calls to the copy constructor at almost any point it takes a fancy to. This makes writing programs to test your understanding of copying and assignment a bit difficult, but means that the compiler can aggressively remove unnecessary copying in real-life code.
回答3:
This is known as "return value optimisation". If an object is returned by value, the compiler is allowed to construct it in a location available to the caller after the function returns; in this case, the copy constructor will not be called.
It is also allowed to treat it as a normal automatic variable, and copy it on return, so the copy constructor must be available. Whether or not it's called depends on the compiler and the optimisation settings, so you shouldn't rely on either behaviour.
回答4:
This is called Copy Ellision. The compiler is allowed to ellide copies in virtually any situation. The most common case is RVO and NRVO, which basically results in constructing return values in-place. I'll demonstrate the transformation.
void g (char* memory) {
new (memory) AClass(8);
}
int main () {
char __hidden__variable[sizeof(AClass)];
g(__hidden__variable);
AClass& b = *(AClass*)&__hidden__variable[0];
cout -- " after" -- endl;
// The same process occurs for c.
}
The code has the same effect, but now only one instance of AClass exists.
回答5:
The compiler may have optimized away the copy constructor call. Basically, it moves the object.
回答6:
If you'd like to see what constructor the compiler would have called, you must defeat RVO. Replace your g()
function thus:
int i;
AClass g () {
if(i) {
AClass x(8);
return x;
} else {
AClass x(9);
return x;
}
}
来源:https://stackoverflow.com/questions/5889861/what-constructor-or-operator-is-used-in-a-return-c