Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When are implicit move constructors not good enough?

When are implicit move constructors not good enough?

Should I treat it like destructors and copy constructors, where it's generally only necessary if I manage my own memory?

Is the implicit move constructor good enough in this (very contrived) scenario:

class A { private:     B b;     std::string name;  public:     A();     std::string getName() const {         return name;     }      B getB() const {         return b;     } };  class B { private:     std::vector list;  public:      B();     std::vector getList() const {         return list;     } }; 
like image 464
DormoTheNord Avatar asked Jun 13 '13 22:06

DormoTheNord


People also ask

What does implicit move constructor do?

Implicitly-defined move constructor For non-union class types (class and struct), the move constructor performs full member-wise move of the object's bases and non-static members, in their initialization order, using direct initialization with an xvalue argument.

Why move constructor is faster than copy constructor?

The move constructor is much faster than a copy constructor because it doesn't allocate memory nor does it copy memory blocks.

Why do we need move constructors?

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

What is the difference between move constructor and move assignment?

The move assignment operator is different than a move constructor because a move assignment operator is called on an existing object, while a move constructor is called on an object created by the operation. Thereafter, the other object's data is no longer valid.


1 Answers

The answer here is based on result of Google search.

Quoting from Andrzej's C++ blog

> When should I define move constructor for my class?

It greatly depends on what your class does and how it is implemented. First, for ‘aggregate’ classes, which only group other data for convenience/clarity, move constructors will be implicitly generated by the compiler. Consider the following class.

struct Country {   std::string name;   std::vector<std::string>  cities; }; 

In a typical C++ struct many special member functions — like copy constructor, copy assignment, destructor — are auto-generated. This also includes move constructor (and move assignment).

For more sophisticated classes, which encapsulate their implementation details, the answer is more interesting. One of the main goals of move semantics (move constructor, move assignment) is to give the compiler two tools for implementing value semantics (passing arguments by value, returning by value) for user defined types:

  1. Making two identical objects out of one — it needs to be expensive.
  2. Moving one object from one memory location to the other — it can be made very fast.

If for your class it is possible to implement move constructor that would be faster than the copy constructor, you should implement it for run-time speed optimization purposes. We have seen how it can be implemented for vector in this link. However, it is not for all types that such move constructor, faster than a copy constructor, can be implemented. Consider the following matrix representation.

class Matrix {   std::complex<long double> data[1000][1000]; }; 

Because all memory required for matrix representation is declared in class scope (unlike in vector, which uses heap-allocated memory) there is no way to apply only a small number of assignments. We will need to do a copying for each array element. There is no point in defining move constructor, as it will be no faster than copying.

Another valid reason for providing your move constructor if you want to enable your type that is non-copyable (because it is RAII-like and represents a resource) to be still passed by value where copying is not required, and stored in STL containers. Such unique ownership semantics are explained in more detail in this link.

like image 69
taocp Avatar answered Sep 20 '22 08:09

taocp