Copy Constructor in C++ Is Called When Object Is Returned from a Function

Copy Constructor in C++ is called when object is returned from a function?

It's called exactly to avoid problems. A new object serving as result is initialized from the locally-defined object, then the locally defined object is destroyed.

In case of deep-copy user-defined constructor it's all the same. First storage is allocated for the object that will serve as result, then the copy constructor is called. It uses the passed reference to access the locally-defined object and copy what's necessary to the new object.

Why is the copy constructor called when we return an object from a method by value

The copy constructor is called because you call by value not by reference. Therefore a new object must be instantiated from your current object since all members of the object should have the same value in the returned instance. Because otherwise you would be returning the object it self, which would be returning by reference. In this case modifying the reference object would change the original as well. This is generally not a behavior one wants when returning by value.

Why does the copy constructor (of a C++ class) get called when a function returns?

The compiler generated copy constructor takes a const reference as the parameter.

An anonymous temporary is allowed to bind to a const reference, so compilation passes.

Note that the implied value copy created by return v; is elided in later C++ standards.

why copy constructor is always called when return by value

I have tried gcc 4.8.4 and vc++ 2015, copy constructor of MyClass is called twice for (2) in both compilers.

Because that is how it is supposed to work!

Really, for the case where you want this to be optimized, there's the reference mechanism in C++; in your case it must not be optimized away, because "I checked" implies that you relied on a side effect of the constructor to show you it's being called; how should the compiler know you don't functionally need that side effect?

Copy constructor not called when initializing an object with return value of a function

#include <iostream>

using namespace std;

class A
{
public:
int a;
A(): a(5)
{
cout << "Constructing: " << (void *)this << std::endl;
}
A(const A &b)
{
a = b.a;
cout << "Copy Constructor: " << (void *)this << " from " << (void *)&b << std::endl;
}
A fun(A a)
{
return a;
}
};

int main()
{

A a, c;
A b = a.fun(c);

std::cout << "a:" << (void *)&a << std::endl <<
"b:" << (void *)&b << std::endl <<
"c:" << (void *)&c << std::endl;
return 0;
}

Yields:

Constructing: 0x7fffbb377220
Constructing: 0x7fffbb377210
Copy Constructor: 0x7fffbb377230 from 0x7fffbb377210
Copy Constructor: 0x7fffbb377200 from 0x7fffbb377230
a:0x7fffbb377220
b:0x7fffbb377200
c:0x7fffbb377210

So it constructs a, constructs c, copies c to an intermediate (argument a of the function), and then copies the intermediate directly into b, skipping the typical copying of a to a return intermediate. This is even better demonstrated if you pass by value (change to A fun(const A& a):

Constructing: 0x7fff8e9642b0
Constructing: 0x7fff8e9642a0
Copy Constructor: 0x7fff8e964290 from 0x7fff8e9642a0
a:0x7fff8e9642b0
b:0x7fff8e964290
c:0x7fff8e9642a0

a is constructed, c is constructed, c is copied directly to b, despite b not being passed to fun!

Why isn't the copy-constructor called when returning LOCAL variable

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.

Why is the copy constructor not called when the function returns?

With the above set-up it is quite likely that the compiler elides the copy constructor and, instead, directly constructs the temporary temp in the location where the return value will be expected. Copy elision is explicitly allowed even if the copy constructor has side effects. However, even if the copy is elided, the copy or move constructor still has to be accessible, i.e., the potential of copy elision doesn't relax the rules on the corresponding constructor to be accessible.

If you feel you absolutely want to have a copy constructor called, you can force copy construction, e.g., by passing the result through an identity function:

template <typename T>
T const& identity(T const& object) {
return object;
}
// ...
return identity(temp);

Normally, you'd want the copy constructor to be elided, however.



Related Topics



Leave a reply



Submit