c++move-semanticsrule-of-five

move constructor/assignment for a trivial class in a linked list


I have a simple class with a few trivial members, and no allocations. I am planning to add a move constructor/assignment. These primitives are not going to be more effective than the normal ones.

Question one: does it make sense to do it in order to make my class more generic?

There is an internal list linking objects of the class.

Question two: what state I should leave the class that was moved from: in the list or removed from the list? I am planning to remove it from the list.

Update: there are several comments on using compiler-generated moves. I cannot do it because there is an internal list I have to take care of.

So, it is either hand-crafted moves or none. The snippet of the possible code is below, there is no multithreading.

class A {
 public:
  static void Run() {
       A* cur = list_;
       while(cur) {
           cur->DoWork();
           cur = cur->next_;
       }
  }
   
  virtual ~A() { Remove(); }

  A() : next_(), data_(), in_list_() {
  }

  A(int data) : next_(), data_(data), in_list() {
    Insert();
  }

  A(A const& other) : next_(), data_(other.data_), in_list() {
    Insert();
  }

  A(A&& other) : next_(), data_(other.data_), in_list() {
    other.Remove();
    Insert();
  }

  A& operator=(A const& other) {
    if (this != &other) {
       data_ = other.data_;
       Insert();
    }
    return *this;
  }

  A& operator=(A&& other) {
    if (this != &other) {
      data_ = other.data_;
      other.Remove();
      Insert();
    }
    return *this;
  }

 private:
    void DoWork() { <do-something-important-with-data>; }

    void Insert() {
      if (_in_list) {
        return;
      }
      ...;
      in_list_ = true;
    }

    void Remove() {
      if (!_in_list) {
        return;
      }
      ...;
      in_list_ = false;
    };

  A* next_;
  int data_;
  bool in_list_;

  static A* list_;
};


Solution

  • After discussion in the comments (thank you, everybody) it seems that I can answer this question myself: (1) it is a good idea to implement the rule-of-five just to support the unique_ptr, (2) the source object of the move should not be in the list after the move is done.