I wrote the following program to test when the copy constructor is called and when the assignment operator is called:
#include
class Test
{
public:
T
No assignment operator is used in the first test-case. It just uses the initialization form called "copy initialization". Copy initialization does not consider explicit constructors when initializing the object.
struct A {
A();
// explicit copy constructor
explicit A(A const&);
// explicit constructor
explicit A(int);
// non-explicit "converting" constructor
A(char const*c);
};
A a;
A b = a; // fail
A b1(a); // succeeds, "direct initialization"
A c = 1; // fail, no converting constructor found
A d(1); // succeeds
A e = "hello"; // succeeds, converting constructor used
Copy initialization is used in those cases that correspond to implicit conversions, where one does not explicitly kick off a conversion, as in function argument passing, and returning from a function.
Your first set is according to the C++ standard, and not due to some optimization.
Section 12.8 ([class.copy]
) of the C++ standard gives a similar example:
class X {
// ...
public:
X(int);
X(const X&, int = 1);
};
X a(1); // calls X(int);
X b(a, 0); // calls X(const X&, int);
X c = b; // calls X(const X&, int);
The last line would be the one matching your case.
C++ standard 8.5/12
The initialization that occurs in argument passing, function return, throwing an exception (15.1), handling an exception (15.3), and brace-enclosed initializer lists (8.5.1) is called copy-initialization and is equivalent to the form
T x = a;
The initialization that occurs in new expressions (5.3.4), static_cast expressions (5.2.9), functional notation type conversions (5.2.3), and base and member initializers (12.6.2) is called direct-initialization and is equivalent to the form
T x(a);