1) Conversion Constructor
struct X {
X(int);
X(const char*, int =0);
X(int, int);
};
void f(X arg) {
X a = 1; // a)
X b = "Jessie"; // b)
a = 2; // a = X(2)
f(3); // f(X(3))
f({1, 2}); // f(X(1,2)) # C++11
}
a) If "-fno-elide-constructor" is specified when compiling, it constructs a temp X(1) first, and then copy construct left hand "a". By default the compile will optimize out the temp object.
b) If "-fno-elide-constructor" is specified when compiling, it constructs a temp X("Jessie",0) first, and then copy construct left hand "b".
So best practice is constructing object in the form of "X a(1) (direct initialization)" instead of "X a = 1 (copy initialization)" or make the constructor "explicit"
An explicit constructor constructs objects just like non-explicit constructors, but does so only where the direct-initialization syntax or where casts are explicitly used.
struct Z {
explicit Z();
explicit Z(int);
explicit Z(int, int);
};
Z a; // OK: default-initialization performed
Z a1 = 1; // error: no implicit conversion
Z a3 = Z(1); // OK: direct initialization syntax used
Z a2(1); // OK: direct initialization syntax used
Z* p = new Z(1); // OK: direct initialization syntax used
Z a4 = (Z)1; // OK: explicit cast used
Z a5 = static_cast<Z>(1); // OK: explicit cast used
Z a6 = { 3, 4 }; // error: no implicit conversion
2) Conversion function (operator)
A conversion function is never used to convert a (possibly cv-qualified) object to the (possibly cv-qualified) same object type (or a reference to it), to a (possibly cv-qualified) base class of that type (or a reference to it), or to (possibly cv-qualified) void.
A conversion function may be explicit , in which case it is only considered as a user-defined conversion for direct-initialization. Otherwise, user-defined conversions are not restricted to use in assignments and initializations.
Conversion functions are inherited.
Conversion functions can be virtual.
Conversion functions cannot be declared static.
conversion-function-id:
operator conversion-type-id
conversion-type-id:
type-specifier-seq conversion-declaratoropt
conversion-declarator:
ptr-operator conversion-declaratoropt
The conversion-type-id shall not represent a function type nor an array type.The conversion-type-id in a conversion-function-id is the longest possible sequence of conversion-declarators.
&ac.operator int*i; // syntax error:
// parsed as: &(ac.operator int *)i
// not as: &(ac.operator int)*i
class Y { };
struct Z {
explicit operator Y() const;
};
void h(Z z) {
Y y1(z); // OK: direct-initialization
Y y2 = z; // ill-formed: copy-initialization
Y y3 = (Y)z; // OK: cast notation
}