javaLover
javaLover

Reputation: 6425

C++ std::move assignment from scratch - low maintainability

I like the new std::move but afraid that it reduces my program maintainability.

To my knowledge, if I create move constructor or move assignment operator=(), I have to write it from scratch. That is where the problem begins.

Code version 1

Here is a tiny class:-

class B{
    M shouldBeMove;  //if it is copied, it is still correct (but prefer move)
    C shouldBeCopy;  //can be copied or moved, both are equal and ok
    //wow, I don't even have to write this line for operator=():-
    //    this->shouldBeCopy = that.shouldBeCopy
}

B b1;
B b2=b1;

Currently, B b2=b1 will copy both M and C. It is ok.

Code version 2

Now I want to use the power of std::move :-

class B{
    M shouldBeMove;  //now, the program is refactored that it must be moved 
    // M now has "M& operator=(M&& that)"
    C shouldBeCopy;
    B& operator=(B&& that){
        this->shouldBeMove=std::move(that.shouldBeMove);
        this->shouldBeCopy=that.shouldBeCopy;   //<-- a bit tedious (1#)
        //  ... imagine that there are 10 variables to be copied ... 
    }
}

B b1;
B b2=std::move(b1);

It is still ok, but a bit tedious. (1#)

Code version 3

Then one month in the future, I may want to add a new field e.g. C shouldBeCopy2 to B, I also have to add a line into operator= :-

B& operator=(B&& that){
    this->shouldBeMove=std::move(that.shouldBeMove);
    this->shouldBeCopy=that.shouldBeCopy;
    this->shouldBeCopy2=that.shouldBeCopy2;  //<--- new line
}

I think I am a type that may forget to add that line. (2#)

Question:

1#. How to make it not tedious?
2#. How to foolproof my mistake?

Upvotes: 2

Views: 87

Answers (1)

Bryan Chen
Bryan Chen

Reputation: 46578

You should follow rule of zero and let compiler generate the constructors and assign operators for you.

But when you need to implement a moveable type, make sure you implement both move assignment operator (T& operator=(T&&)) and move constructor (T(T&&)). Please follow rule of five and ensure the class have proper copy constructor/move constructor/copy assignment operator/move assignment operator/destructor

https://ideone.com/UVZNOM

#include <iostream>
using namespace std;

class M{
    public: int database=0;
    M& operator=(M&& other){
        this->database=other.database;
        other.database=0;
        return *this;

    }
    M(M &&other) {
        *this = std::move(other);
    }
    M (M& m)=default;
    M ()=default;
    ~M() { /* free db */ }
};
class B{ // As rule of zero, you don't need to implement constructors and assignment operators 
    public: M shouldMove;
};

int main() {
    B b;
    b.shouldMove.database=5;
    B b2=std::move(b);
    std::cout<< b.shouldMove.database <<std::endl;
    std::cout<< b2.shouldMove.database <<std::endl;
    return 0;
}

Upvotes: 1

Related Questions