Explicit copy constructor
The explicit copy constructor means that the copy constructor will not be called implicitly, which is what happens in the expression:
CustomString s = CustomString("test");
This expression literally means: create a temporary CustomString
using the constructor that takes a const char*
. Implicitly call the copy constructor of CustomString
to copy from that temporary into s
.
Now, if the code was correct (i.e. if the copy constructor was not explicit), the compiler would avoid the creation of the temporary and elide the copy by constructing s
directly with the string literal. But the compiler must still check that the construction can be done and fails there.
You can call the copy constructor explicitly:
CustomString s( CustomString("test") );
But I would recommend that you avoid the temporary altogether and just create s
with the const char*
:
CustomString s( "test" );
Which is what the compiler would do anyway...
Explicit copy constructor behavior and practical uses
I believe the relevant sections of C++03 are §12.3.1 2:
An explicit constructor constructs objects just like non-explicit constructors, but does so only where the direct-initialization syntax (8.5) or where casts (5.2.9, 5.4) are explicitly used. A default constructor may be an explicit constructor; such a constructor will be used to perform default-initialization or value-initialization (8.5).
and § 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);
Calling passByValue(a)
involves copy-initialization, not direct-initialization, and thus should be an error, according to C++03 § 12.3.1 2.
Explicit keyword, move constructor and copy constructor, and disabling move and copy constructor
An explicit copy constructor works the same way as an explicit converting constructor - it cannot be invoked implicitly. The only difference is what your object is constructed from.
I would also believe that the uses cases for this are extremely rare and far between.
Slightly more common case is to have the class' copy constructor and assignment operator deleted (= delete
). This is useful for objects that represent a unique resource, and therefore should not be copied. std::cout
is an example of an object that exists, but should not be copied.
Explicit Copy constructor call syntax
No, they are not the same. C++ Standard section § 12.3.1 [class.conv.ctor]
An explicit constructor constructs objects just like non-explicit
constructors, but does so only where the direct-initialization syntax
(8.5) or where casts (5.2.9, 5.4) are explicitly used
Base b(a); // Direct initialization
Base b=a; // Copy initialization
Copy initialization (using =
) doesn't consider explicit constructors, but direct initialization (using ()
) does.
You'll have to use a cast or make your constructor non explicit if you want to use copy initialization.
Should an explicit copy constructor be ignored?
§ 12.3.1 [class.conv.ctor]/p2:
An explicit constructor constructs objects just like non-explicit constructors, but does so only where the
direct-initialization syntax (8.5) or where casts (5.2.9, 5.4) are explicitly used.
Example 1:
CL cl2 = 5;
§ 8.5 [dcl.init]/p17:
The function selected is called with the initializer expression as its
argument; if the function is a constructor, the call initializes a temporary of the cv-unqualified
version of the destination type. The temporary is a prvalue. The result of the call (which is the
temporary for the constructor case) is then used to direct-initialize, according to the rules above,
the object that is the destination of the copy-initialization.
In direct-initialization, explicit
constructors can be considered, so the error is not expected. GCC trunk already compiles this example successfully. This was bug 54521.
Example 2:
CL cl3 = (CL)5;
In this case, that cast syntax performs a static_cast
:
§ 5.2.9 [expr.static.cast]/p4:
An expression
e
can be explicitly converted to a typeT
using astatic_cast
of the formstatic_cast<T>(e)
if the declarationT t(e);
is well-formed, for some invented temporary variablet
(8.5). The effect of such an
explicit conversion is the same as performing the declaration and initialization and then using the temporary
variable as the result of the conversion.
The rhs is of type CL
, and the (copy-)initialization requires a non-explicit
constructor, thus the error is expected.
explicit copy constructor compile error
You defined an explicit copy constructor, but the functions
Vector Vector::operator+(const Vector& v) const
and
Vector Vector::operator-(const Vector& v) const
must return by value, and cannot anymore, due to explicit
(in other words, they cannot copy tmp
into the returned object).
I also was checking new stuff from C++11 and occurred that I can declare my constructor like a moving-constructor
explicit Vector(const Vector&& v);
and the code compiles just fine. If I do that, do I have to have both copy and move constructors?
Not sure I understand what you mean here. You will have the same issue if you only declare an explicit move constructor (which will prevent the compiler from generating a default copy constructor). I am not able to produce a "compilable" code.
Behaviour of explicit copy constructor
This:
A aa = A10x10;
Performs copy initialization. Copy initialization works by converting the object to the type of the object being initialized. However, copy initialization does this by implicit conversion. And implicit conversion cannot call an explicit
constructor.
Even if it's the copy constructor.
Now by all rights, you'd think you would get a compile error. But you don't. Why? Because A
is implicitly convertible by user-defined conversion to bool
. And bool
is convertible by standard conversion to int
. And A
can in fact be constructed from a single value of type int
. And while implicit conversion allows only one user-defined conversion, it does allow a user-defined conversion followed by a standard conversion.
So that's what happens. It's why the first value in aa
is 0 when the copy constructor is explicit
.
Generally speaking, always make operator bool
explicit
. And never make the copy constructor explicit
.
Explicit copy constructor of a parameter passed via std::async
In the post-C++20 draft (https://timsong-cpp.github.io/cppwp/n4868/futures.async) there is a "Mandates:" clause which effectively only requires std::is_move_constructible_v<A>
to be satisfied. This tests whether a declaration of the form
A a(std::declval<A&&>());
would be well-formed, which it is even with explicit
on the constructor. Therefore the "Mandates:"-clause is satisfied. (If it was not, the program would be ill-formed.)
However there is also a "Precondition:" clause effectively requiring A
to be Cpp17MoveConstructible. This library concept has the effective requirement that
A a = rv;
where rv
is a rvalue of type A
(see https://timsong-cpp.github.io/cppwp/n4868/library#tab:cpp17.moveconstructible), is well-formed. This is not the case here, since this is copy-initialization which doesn't consider explicit
constructors. Theferore the "Precondition:" clause is not satisfied, which causes the program to have undefined behavior.
As a result both behaviors are conforming.
However, in the current draft the precondition has been removed with resolution of LWG issue 3476 (draft commit) and I don't see anything else that would forbid the type from being usable as an argument to std::async
. The arguments are now specified to be constructed with auto(/*...*/)
which does consider explicit constructors. The resolution of the mentioned issue explicitly says that no other copy/move should be allowed either.
Explicit on copy constructor makes compilation error in c++. Who is responsible for casting?
It seems like you are passing the pointer bArr
to a reference argument. You may want to dereference the pointer first:
*result =foo(*bArr, _b1)/goesTo;
Also I am 99% sure that is exactly what the error message states.
To answer your question. There is no implicit conversion(casting) from pointer to reference. You must explicitly use the dereference operator - prefixed*
. Copy constructor is not a casting operator nor is casting operator a constructor.
Casting operator in class T
converts from T
to some other type. Copy constructor copies one instance of T
to another instance of T
. Ordinary constructor with one argument of some other type can be seen as converting said other type to an instance of type T
.
EDIT: As pointed by Pete Becker this doesn't fix the problem as the explicit A(const double *arr2)
is marked as explicit thus prohibiting the compiler doing the one implicit conversion that it's allowed to do.
So correct solution is to directly create A
from bArr
or mark it as implicit
What actually happens when copy initializing in C++?
The effect of copy initialization here is,
(emphasis mine)
If T is a class type, and the cv-unqualified version of the type of other is not T or derived from T, or if T is non-class type, but the type of other is a class type, user-defined conversion sequences that can convert from the type of other to T (or to a type derived from T if T is a class type and a conversion function is available) are examined and the best one is selected through overload resolution. The result of the conversion, which is a
prvalue temporary (until C++17)
prvalue expression (since C++17)
if a converting constructor was used, is then used to direct-initialize the object.The last step is usually optimized out and the result of the conversion is constructed directly in the memory allocated for the target object, but the appropriate constructor (move or copy) is required to be accessible even though it's not used. (until C++17)
Note that the ojbect is direct-initialized from the converted A
(from int
), the copy constructor is marked as explicit
or not doesn't matter here.
BTW: Since C++17 because of mandatory copy elision, the copy-construction will be elided completely.
Under the following circumstances, the compilers are required to omit the copy and move construction of class objects, even if the copy/move constructor and the destructor have observable side-effects. The objects are constructed directly into the storage where they would otherwise be copied/moved to. The copy/move constructors need not be present or accessible:
Related Topics
Using Std:Fstream How to Deny Access (Read and Write) to the File
What Is the Use of 0-Length Array (Or Std::Array)
How Are Local and Global Variables Initialized by Default
What Does "Void *(*)(Void *)" Mean in C++
Diamond Inheritance Lowest Base Class Constructor
How to Use Cin.Fail() in C++ Properly
Can't Modify Char* - Memory Access Violation
What Is "Strip" (Gcc Application) Used For
How to Compile for Windows Xp with Visual Studio 2012
How to Use C++11 Enum Class for Flags