Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to ensure the move constructor is used

The code below gives the error:

use of deleted function ‘constexpr B::B(const B&)’

now, I know this happens because the copy constructor is (intentionally) implicitly deleted by specifying a move constructor, and that copying the vector causes the calls to the (deleted) copy constructor. I think I also understand why the vector's copy constructor and assignment operator are used. I clearly want to use the move constructor and assignment operator though: move the object, so also move the vector it contains. So, how do I get my move constructor/assignment operator to use the vector's move constructor/assignment operator?

Here is the code:

#include <vector>

class B {
private:
    /* something I don't want to copy */
public:
    B() {};
    B(B&& orig) {/* move contents */};
    B& operator=(B&& rhs) {
        /* move contents */
        return *this;
    };
};

class A {
private:
    vector<B> vec;
public:
    A() : vec() {};
    A(A&& orig) : vec(orig.vec) {};
    A& operator=(A&& rhs) {
        vec = rhs.vec;
        return *this;
    };
};
like image 274
Oebele Avatar asked Feb 12 '16 09:02

Oebele


People also ask

Where is the move constructor used?

A move constructor enables the resources owned by an rvalue object to be moved into an lvalue without copying. For more information about move semantics, see Rvalue Reference Declarator: &&. This topic builds upon the following C++ class, MemoryBlock , which manages a memory buffer.

How does move constructor work?

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.

Is move constructor automatically generated?

No move constructor is automatically generated.

How is move constructor called?

A constructor is called a 'move constructor' when it takes an rvalue reference as a parameter.


1 Answers

Just call std::move on the vectors in the expression in which you want to move from them:

class A {
private:
    vector<B> vec;
public:
    A() : vec() {};
    A(A&& orig) : vec(std::move(orig.vec)) {};
    //                ^^^^^^^^^
    A& operator=(A&& rhs) {
        vec = std::move(rhs.vec);
        //    ^^^^^^^^^
        return *this;
    };
};

Even though you take in rvalue references, rhs and orig are still lvalues in the function, so you need to call std::move on them.

like image 104
TartanLlama Avatar answered Oct 05 '22 23:10

TartanLlama