Reputation: 3526
This is my attempt to understand how class initialization works. I'm not sure about everything, and that is why I'm asking this question. This is what I believe happens when we do the following:
T t = u;
Constructs an object of type T
from u
. This then becomes:
T t = T(u);
Calls the copy-constructor:
T t( T(u) );
Okay the second is the part I'm not understanding. I read somewhere that T t = u
is made into T t(T(u))
. But if that is true why doesn't this print "copy-constructor":
struct T
{
template <class U>
T(U) {
std::cout << "constructs an object of type T...\n";
}
T(T const &)
{
std::cout << "copy-constructor";
}
T& operator=(T const &)
{
std::cout << "assignment operator"; return *this;
}
T() = default;
};
int main()
{
T t(T(5));
}
Actually, all this does is print "constructs an object of type T". Why isn't the copy-constructor called here? T(5)
can be made into an object of type T const &
which is passed into the constructor of T
so shouldn't the appropriate constructor be called.
I'd really like some insight to this. I've been trying to understand this for a while.
Upvotes: 2
Views: 88
Reputation: 76245
There's a special rule for this situation. The compiler is allowed to skip the copy constructor, even though it has side effects, provided the expression with the copy constructor would have been legal. So
T t = u;
is, as you say, equivalent to
T t(T(u));
The compiler skips the copy constructor and treats this as
T t(u);
One situation where this would not be allowed would be a class with a private copy constructor. In that case, T t(T(u));
would not be legal, and the compiler would not be allowed to make it legal by skipping the copy constructor.
Upvotes: 4