why copy constructor is called when we return an object from a method by value. please see my below code in that i am returning an object from a method while returning control is hitting the copy constructor and then returning. i am not understood following things:
1) why it is calling copy constructor.
2)which object is passing implicitly to copy constructor,
3)to which object copy constructor will copy the content,
4)what is the necessity of copying the object content while returning. so plz help.
#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;
class ClassA
{
int a, b;
public:
ClassA()
{
a = 10;
b = 20;
}
ClassA(ClassA &obj)
{
cout << "copy constructor called" << endl;
}
};
ClassA function (ClassA &str)
{
return str;
}
int main ()
{
ClassA str;
function(str);
//function(str);
return 0;
}
I'll try to answer all the questions at once.
The behavior you are observing is due to the way returning an object by value works in C++. First, a temporary object is copy-constructed (or move-constructed, in C++11) from the value returned by your function. Then, if this return value is used to initialize another object, such as in:
Class c = fxn();
The object c
is copy-constructed (or move-constructed, in C++11), from that temporary.
This said, an implementation is allowed to elide one (in your concrete case) or both of these calls to the copy or move constructor per paragraph 12/8.31 of the C++11 Standard even though those constructors have side effects, and construct the function's return value directly in c
:
When certain criteria are met, an implementation is allowed to omit the copy/move construction of a class object, even if the constructor selected for the copy/move operation and/or the destructor for the object have side effects. In such cases, the implementation treats the source and target of the omitted copy/move operation as simply two different ways of referring to the same object, and the destruction of that object occurs at the later of the times when the two objects would have been destroyed without the optimization.122 This elision of copy/move operations, called copy elision, is permitted in the following circumstances (which may be combined to eliminate multiple copies):
— 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— [...]
— when a temporary class object that has not been bound to a reference (12.2) would be copied/moved to a class object with the same cv-unqualified type, the copy/move operation can be omitted by constructing the temporary object directly into the target of the omitted copy/move
— [...]
The reason why I wrote that in your specific case only one of the calls to the copy or move constructor can be elided is the sentence in bold in the first bullet of the Standard quote above:
[...] (other than a function or catch-clause parameter) [...]
If you are returning a parameter of your function, copy elision is inhibited.
Also notice, that the signature of your constructor should be:
Class(Class const& c)
// ^^^^^
There is no reason for you to accept an lvalue reference to non-const
in the copy constructor, since you are not going to modify the object you are copying from.
Even worse, the above would prevent copy construction from rvalues (like temporaries), so the following code would not compile:
Class foo() { return Class(); }
Even though an implementation is allowed to elide the copy, a viable and accessible copy constructor (or move constructor, if we're talking about a move) should still be present.