Reputation: 143865
Compare these two initialization methods in C++ for a trivial complex number class.
complx one(1,3);
complx two = complx(3,4);
In the second case, will I get a constructor followed by an assignment, followed by a copy, or just the constructor?
Is it possible to distinguish the two types of initializations ?
Upvotes: 3
Views: 133
Reputation: 110698
complx two = complx(3,4);
This is a copy-initialization. The particular semantics for this initializer are covered by this rule:
If the initialization is direct-initialization, or if it is copy-initialization where the cv-unqualified version of the source type is the same class as [...] the class of the destination, constructors are considered. The applicable constructors are enumerated (13.3.1.3), and the best one is chosen through overload resolution (13.3). The constructor so selected is called to initialize the object, with the initializer expression or expression-list as its argument(s). [...]
That is, a copy-initialization where the source type is the same as the destination type behaves like a direct-initialization. So that makes the declaration equivalent to:
complx two(complx(3,4));
This constructs a temporary complx
object and then uses the copy/move constructor to construct two
.
However, this copy/move may be elided:
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
However, the copy constructor must still be accessible, as though it were being called.
Can the two initializations be distinguished? Assuming the copy/move is valid, not reliably, no. If the compiler does elide the copy in the copy-initialization or if the copy is well behaved and doesn't have any extra side effects, then both will behave exactly the same. If it does not elide the copy and the copy has some extra side effects, then you will notice a difference.
Upvotes: 4
Reputation: 1639
In C++ you can distinguish the two types of initializations by implementing a move constructor or a copy constructor like this
struct complx
{
complx(complx && aOther){} // <- move constructor (C++11)
complx(const complx & aOther){} // <- copy constructor (C++03)
complx(float a, float b) {} // <- normal constructor
};
Your first line of code will call the normal constructor.
Your second line of code is called copy initialization with an rvalue, and will call the move constructor in C++11 and the copy constructor in C++03. Note that in C++03, complx(complx && aOther){}
is not recognized (invalid syntax), and should be removed.
Upvotes: 0
Reputation: 206566
First is known as Direct Initialization.
It simply calls the best match constructor.
Second case is known as Copy initialization.
it creates a object of type Complx
and then copies that object to create the two
object.
so it involves call to the constructor followed by a copy constructor call.
The compilers are allowed to elide the copy constructor call in general whenever they can(there are special conditions, the code example meet those conditions). But none of the optimizations are guaranteed and they depend on the efficiency of the compiler implementation so the copy constructor needs to be available for second example to compile.
Is it possible to distinguish the two types of initializations ?
Yes, second example will not compile unless a copy constructor is available and accessible.
Good Read:
Upvotes: 3