Reputation: 816
I'm relatively new to C++. Say, I have a toy class as follows:
class Date {
public:
Date()
{
cout << "default constructor\n";
}
Date(int year, int month, int day)
{
cout << "constructor\n";
}
Date(const Date& d)
{
cout << "copy constructor\n";
}
Date& operator=(const Date& d)
{
cout << "copy assignment\n";
return *this;
}
};
If I initialize a Date
object using Date d = Date{ 2012,12,31 };
I would expect an unnamed temporary object of type Date
first to be constructed according to the right-hand side, then, the value of the temporary to be copied into d
on the left-hand side. If so, I expect my program to print out constructor
and then copy constructor
. However, the result implies that the copy constructor is not used as it only prints constructor
:
Date d = Date{ 2012,12,31 }; // constructor
On the other hand, copy assignment and copy construction work as expected:
Date d1; // default constructor
d1 = Date{ 2012,12,31 }; // constructor
// copy assignment
Date d2 = d1; // copy constructor
My current guesses for Date d = Date{ 2012,12,31 };
:
Compiler treats Date d = Date{ 2012,12,31 };
as Date{ 2012,12,31 };
i.e. compiler kind of "optimizes" Date d =
away and generates object code for Date{ 2012,12,31 };
First, the unnamed temporary is constructed according to Date{ 2012,12,31 };
, then, the system somehow attaches the name d
to that temporary and somehow turns it in to a "normal" object.
May I ask which one of my guesses is correct?
Or if they are both wrong, could anyone tell me why code like Date d = Date{ 2012,12,31 };
does not call copy constructor? (if it is an optimization, why wouldn't d1 = Date{ 2012,12,31 };
just discard the old d1
, create the new object and name it d1
?)
A follow-up question:
In my current understanding, what is returned by a function is a temporary which holds the return value.
Let day()
be a function call of a function whose return type is Date
. Consider:
Date d3 = day();
Now, if my second guess is correct, then, is it possible that the object we get from this line the temporary returned by day()
which is attached with the name d3
? If so, is it possible that d3
might be unintentionally destroyed after this line as it was a temporary? (I know that if a reference is attached to a temporary, the lifetime of that temporary will be extended to meet the lifetime of the reference, but I think here we are in a different situation)
More to the point, may I ask how does C++ ensure that Date d3 = day();
copies the value from day()
to d3
?
Many thanks!
Upvotes: 1
Views: 541
Reputation: 238311
Date d = Date{ 2012,12,31 };
Pre-C++17: As specified for the abstract machine, a temporary object is created and the variable is copy-initialised. But this copy is allowed to be optimised and instead the variable is initialised directly without the temporary object having existed in the first place. This is called copy elision.
Post-C++17: The initialiser for the prvalue is used to initialise the variable. There is no temporary object and no optimisation is required. This is same as the optimised pre-C++17 behaviour except it is guaranteed rather than only allowed.
Upvotes: 2