Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Move constructor is required even if it is not used. Why?

Tags:

c++

std

c++11

c++14

Why?! Why C++ requires the class to be movable even if it's not used! For example:

#include <iostream>
using namespace std;

struct A {
    const int idx;
    //   It could not be compileld if I comment out the next line and uncomment
    // the line after the next but the moving constructor is NOT called anyway!
    A(A&& a) : idx(a.idx) { cout<<"Moving constructor with idx="<<idx<<endl; }
   //  A(A&& a) = delete;
    A(const int i) : idx(i) { cout<<"Constructor with idx="<<i<<endl; }
    ~A() { cout<<"Destructor with idx="<<idx<<endl; }
};

int main()
{
    A a[2] = { 0, 1 };
   return 0;
}

The output is (the move constructor is not called!):

Constructor with idx=0
Constructor with idx=1
Destructor with idx=1
Destructor with idx=0

The code can not be compiled if moving constructor is deleted ('use of deleted function ‘A::A(A&&)’'. But if the constructor is not deleted it is not used! What a stupid restriction? Note: Why do I need it for? The practical meaning appears when I am trying to initialize an array of objects contains unique_ptr field. For example:

// The array of this class can not be initialized!
class B {
    unique_ptr<int> ref;
public:
    B(int* ptr) : ref(ptr)
        {  }
}
// The next class can not be even compiled!
class C {
    B arrayOfB[2] = { NULL, NULL };
}

And it gets even worse if you are trying to use a vector of unique_ptr's.

Okay. Thanks a lot to everybody. There is big confusion with all those copying/moving constructors and array initialization. Actually the question was about the situation when the compiler requires a copying consrtuctor, may use a moving construcor and uses none of them. So I'm going to create a new question a little bit later when I get a normal keyboard. I'll provide the link here.

P.S. I've created more specific and clear question - welcome to discuss it!

like image 975
Sap Avatar asked Dec 03 '22 19:12

Sap


1 Answers

A a[2] = { 0, 1 };

Conceptually, this creates two temporary A objects, A(0) and A(1), and moves or copies them to initialise the array a; so a move or copy constructor is required.

As an optimisation, the move or copy is allowed to be elided, which is why your program doesn't appear to use the move constructor. But there must still be a suitable constructor, even if its use is elided.

like image 60
Mike Seymour Avatar answered Dec 28 '22 23:12

Mike Seymour