Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can a move constructor be implicit?

Consider the following class:

class A
{
public:
   std::string field_a;
   std::string field_b;
}

Now consider the following copy construction:

A a1(a2);

The copy construction will adequately copy A despite the lack of of an explicit copy constructor because the copy constructors for std::string will be called by the compiler generated implicit copy constructor.

What I wish to know is, is the same true for move construction?

EDIT: Testing here shows that:

A a2(std::move(a1));

Will actually result in a copy construction, unless the specific move constructor:

A( A && other ) : a(std::move(other.a)) {}

Is defined.

EDIT EDIT I pinged Stephan T Lavavej and asked him why VC 2012 doesn't seem to follow what draft 12.8 states regarding implicit move constructor generation. He was kind enough to explain:

It's more of a "feature not yet implemented" than a bug. VC currently implements what I refer to as rvalue references v2.0, where move ctors/assigns are never implicitly generated and never affect the implicit generation of copy ctors/assigns. C++11 specifies rvalue references v3.0, which are the rules you're looking at.

like image 595
Benj Avatar asked Nov 12 '12 13:11

Benj


People also ask

Should move constructor be const?

A move constructor should normally take a non-const reference. If it were possible to move from a const object it would usually imply that it was as efficient to copy an object as it was to "move" from it. At this point there is normally no benefit to having a move constructor.

Why should move constructor be Noexcept?

noexcept is nice for two reasons: The compiler can optimize a little better because it doesn't need to emit any code for unwinding a call stack in case of an exception, and. It leads to incredible performance differences at runtime for std::vector (and other containers, too)

What is the difference between a move constructor and a copy constructor?

Move constructor moves the resources in the heap, i.e., unlike copy constructors which copy the data of the existing object and assigning it to the new object move constructor just makes the pointer of the declared object to point to the data of temporary object and nulls out the pointer of the temporary objects.


1 Answers

Yes, from the C++11 draft, 12.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,
  • 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.

The last condition is specified with more detail later:

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.

Plainly speaking, the move constructor will be implicitly declared if:

  1. The class does not have user-declared any of the other special member functions.
  2. The move constructor can be sensibly implemented by moving all its members and bases.

Your class obviously complies with these conditions.

like image 141
rodrigo Avatar answered Oct 04 '22 04:10

rodrigo