Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why no default move-assignment/move-constructor?

I'm a simple programmer. My class members variables most often consists of POD-types and STL-containers. Because of this I seldom have to write assignment operators or copy constructors, as these are implemented by default.

Add to this, if I use std::move on objects not movable, it utilizes the assignment-operator, meaning std::move is perfectly safe.

As I'm a simple programmer, I'd like to take advantage of the move-capabilities without adding a move constructor/assignment operator to every class I write, as the compiler could simply implemented them as "this->member1_ = std::move(other.member1_);..."

But it doesn't (at least not in Visual 2010), is there any particular reason for this?

More importantly; is there any way to get around this?

Update: If you look down at GManNickG's answer he provides a great macro for this. And if you didn't know, if you implement move-semantics you can remove the swap member function.

like image 380
Viktor Sehr Avatar asked Jan 27 '11 17:01

Viktor Sehr


People also ask

Does compiler provide default move constructor?

Compilers provide a default: Constructor (no arguments) unless another constructor with arguments is declared.

Does STD move move constructor?

std::move is actually just a request to move and if the type of the object has not a move constructor/assign-operator defined or generated the move operation will fall back to a copy.

Is move constructor automatically generated?

No move constructor is automatically generated.

Why do we need move constructor?

A move constructor enables the resources owned by an rvalue object to be moved into an lvalue without copying.


2 Answers

The implicit generation of move constructors and assignment operators has been contentious and there have been major revisions in recent drafts of the C++ Standard, so currently available compilers will likely behave differently with respect to implicit generation.

For more about the history of the issue, see the 2010 WG21 papers list and search for "mov"

The current specification (N3225, from November) states (N3225 12.8/8):

If the definition of a class X does not explicitly declare a move constructor, one will be implicitly declared as defaulted if and only if

  • X does not have a user-declared copy constructor, and

  • X does not have a user-declared copy assignment operator,

  • X does not have a user-declared move assignment operator,

  • X does not have a user-declared destructor, and

  • the move constructor would not be implicitly defined as deleted.

There is similar language in 12.8/22 specifying when the move assignment operator is implicitly declared as defaulted. You can find the complete list of changes made to support the current specification of implicit move generation in N3203: Tightening the conditions for generating implicit moves , which was based largely on one of the resolutions proposed by Bjarne Stroustrup's paper N3201: Moving right along.

like image 121
James McNellis Avatar answered Sep 20 '22 12:09

James McNellis


Implicitly generated move constructors have been considered for the standard, but can be dangerous. See Dave Abrahams's analysis.

In the end, however, the standard did include implicit generation of move constructors and move assignment operators, though with a fairly substantial list of limitations:

If the definition of a class X does not explicitly declare a move constructor, one will be implicitly declared as defaulted if and only if
— X does not have a user-declared copy constructor,
— X does not have a user-declared copy assignment operator,
— X does not have a user-declared move assignment operator,
— X does not have a user-declared destructor, and
— the move constructor would not be implicitly defined as deleted.

That's not quite all there is to the story though. A ctor can be declared, but still defined as deleted:

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,
— 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,
— any direct or virtual base class or non-static data member of a type with a destructor that is deleted or inaccessible from the defaulted constructor,
— for the copy constructor, a non-static data member of rvalue reference type, 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.

like image 36
Jerry Coffin Avatar answered Sep 19 '22 12:09

Jerry Coffin