What would be the correct way to implement a move constructor considering the following class:
class C {
public:
C();
C(C&& c);
private
Since std::string
itself has a move-ctor, the implicitly defined move-ctor for C
will take care of the proper move operation. You may not define it yourself. However, if you have any other data member and specifically:
12.8 Copying and moving class objects
12 An implicitly-declared copy/move constructor is an inline public member of its class. A defaulted copy- /move constructor for a class X is defined as deleted (8.4.3) if X has:
— a variant member with a non-trivial corresponding constructor and X is a union-like class,
— a non-static data member of class type M (or array thereof) that cannot be copied/moved because overload resolution (13.3), as applied to M’s corresponding constructor, results in an ambiguity or a function that is deleted or inaccessible from the defaulted constructor, or
— a direct or virtual base class B that cannot be copied/moved because overload resolution (13.3), as applied to B’s corresponding constructor, results in an ambiguity or a function that is deleted or inaccessible from the defaulted constructor, or
— for the move constructor, a non-static data member or direct or virtual base class with a type that does not have a move constructor and is not trivially copyable.
13 A copy/move constructor for class X is trivial if it is neither user-provided nor deleted and if
— class X has no virtual functions (10.3) and no virtual base classes (10.1), and functions (10.3) and no virtual base classes (10.1), and
— the constructor selected to copy/move each direct base class subobject is trivial, and
— for each non-static data member of X that is of class type (or array thereof), the constructor selected to copy/move that member is trivial; otherwise the copy/move constructor is non-trivial.
you may want to implement your own move-ctor.
In case you need the move-ctor, prefer the initializer list syntax. Always! Otherwise, you may end up with a default construction per object not mentioned in the initializer list (which is what you're forced for member objects with non-default ctors only).
Both your variants will move the string. The second variant should be preferred because it will not default construct an empty string just to move assign it afterwards.
Check your testcase and then your compiler's bugzilla list. You need to trace calls to both string::operator=(string&&)
(1st case) and string::string(string&&)
(2nd case) if you want to ensure for both cases that they move.
Both Constructors should work. So both are correct move constructors. The second one might be more efficient, since the first one default constructs string
only to assign to it, while the second will simply move construct it and should therefore be more efficient. If the second one is less efficient I would suspect a compiler bug (remember that C++11 support is still not complete for current compilers) or a flawed test methology (how exactly do you test copy vs move and are you sure the move constructor not the assignment op is called in both cases?).
Of course whenever possibly you could simply let the compiler generate your constructor via C(C&&) = default;
.
There is no need to implement a move constructor here since you don't have to manually manage memory. Move constructors are only useful when you manually use dynamic arrays in your class.
You can still explicitly have the compiler create the default move constructor even though it should have already been done even if you don't request it:
C(C&& c) = default;