I can't figure out why the copy-constructor is not called when I try to return a local variable defined within a function. See the following simplified example:
#include <iostream>
using namespace std;
class X {
public:
X() { cout << "Default Constructor" << endl; }
X(const X&) { cout << "Copy Constructor" << endl; }
};
X f(X x) { return x; }
X g() {
X y;
return y;
}
int main() {
cout << "First create an object" << endl;
X a;
cout << "Call f()" << endl;
f(a);
cout << "Call g()" << endl;
g();
}
The output of the complied program is as follows
First create an object
Default Constructor
Call f()
Copy Constructor
Copy Constructor
Call g()
Default Constructor
I understand what's going on when calling f()
, but have no idea why return y
inside the call of g()
does not trigger the copy-constructor.
The reason the copy constructor is not called is because the copy constructor itself is a function with one parameter. You didn't call such function,so it didn't execute.
The copy constructor is invoked when a temporary object is created as the result of a function returning an object.
When we create our own copy constructor, we pass an object by reference and we generally pass it as a const reference. One reason for passing const reference is, we should use const in C++ wherever possible so that objects are not accidentally modified.
In Java it simply copies the reference. The object's state is not copied so implicitly calling the copy constructor makes no sense. And that's all there is to it really.
The compiler optimizes away the return copy. This is known as NRVO (Named Return Value Optimization).
in a return statement in a function with a class return type, when the expression is the name of a non-volatile automatic object (other than a function or catch-clause parameter) with the same cv-unqualified type as the function return type, the copy/move operation can be omitted by constructing the automatic object directly into the function’s return value
The compiler is allowed to do this, even if the copy constructor has side effects.
When certain criteria are met, an implementation is allowed to omit the copy/move construction of a class object, even if the copy/move constructor and/or destructor for the object have side effects.
That is, if you give your copy/move constructors side effects, your program has multiple valid execution paths, depending on whether your compiler wants to optimize or not.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With