Reputation: 72281
The explicit
keyword is recommended for all most constructors which can be called with one argument, except for copy constructors.
For copy constructors, it has a use (to forbid implicit copying via function call, return, etc), but it's not what's usually wanted.
What about move constructors? Is there any reasonable use case to make them explicit? What's the good practice here?
Upvotes: 33
Views: 7838
Reputation: 14987
When returning by value from a function, an implicit move constructor can usually make the process more efficient.
Upvotes: 0
Reputation: 5538
The actual question is how explicit move constructor could possibly be used? It wouldn't be able to be invoked on rvalues, so compiler would have to always select a copy constructor, if available, or fail to compile.
Edit: here is the link to example: http://www.ideone.com/nm7KM
Upvotes: 3
Reputation: 92301
The explicit
keyword is recommended for (single argument) converting constructors, to avoid surprising conversions in unexpected places.
Copy constructors and move constructors are hardly "surprising" in that sense. They happen largely where expected. If you don't want them, I would expect them to be marked =delete
rather than made explicit.
Upvotes: 7
Reputation: 35449
An explicit
move constructors can affect compatibility with e.g. Standard algorithms. For instance, std::swap<T>
requires that T
be MoveConstructible. In turn, MoveConstructible is specified in terms of an expression, namely T u = rv;
(where rv
is an rvalue of type T
).
If there is neither a non-explicit copy constructor nor a non-explicit move constructor for a given type then T u = rv;
is invalid and that type can't be used with std::swap
. (In this particular instance however it is possible to specialize std::swap
to provide the desired functionality, e.g. by using T u(rv);
).
Put more simply, an explicit
move or copy constructor defies expectations and can't be used as well with generic code.
Some other parts of the Standard library that put a MoveConstructible requirement:
unique_ptr<T, D>
bind
(all the decayed types that are passed are concerned)thread
, async
, call_once
(all specified in terms of call wrappers)sort
, stable_sort
, nth_element
, sort_heap
Upvotes: 30
Reputation: 146968
You probably want an implicit move constructor for the majority of uses. They generally fall into the same categories as copy constructors. Explicit isn't recommended for all one-argument constructors, but it is recommended for most. Move constructors are not on that list.
Upvotes: 7