4

I am new to c++11 and wrote the following code to understand how std::move works:

#include <queue>
#include <stdio.h>

class X {
 public:
  X(int x) : x_(x) {}
  ~X() {
    printf("X(%d) has be released.\n", x_);
  }

  X(X&&) = default;
  X& operator = (X&&) = default;

  X(const X&) = delete;
  X& operator = (const X&) = delete;
 private:
  int x_;
};


int main() {
  std::queue<X> xqueue;
  for (int x = 0; x < 5; ++x) {
    xqueue.push(std::move(X(x)));
  }
  return 0;
}

However, it generates the following output, which indicates that the destructor of each X(n) has been called twice:

X(0) has be released.
X(1) has be released.
X(2) has be released.
X(3) has be released.
X(4) has be released.
X(0) has be released.
X(1) has be released.
X(2) has be released.
X(3) has be released.
X(4) has be released.

I can imagine the second round of the output happens right at the end of main() function, and the first round probably happens in the loop when those intermediate Xs ran out of scope.

But, I thought the ownership of such intermediate Xs will be perfectly transferred into the queue and their destructors should not be called during their ownership transfer.

So my questions are:

  1. When I saw an instance being deallocated twice, does that mean it performs copy instead of move?
  2. If the above answer is yes, then how can I really avoid copying?

Thank you,

keelar
  • 5,814
  • 7
  • 40
  • 79

2 Answers2

6

If you move from one object to another object, you still have two objects in total. They both need to be destroyed. Perhaps move is a slightly misleading term, but it is not the object itself that is moved from one place to another (objects never actually move) - it's the contents of the object.

  1. No. As stated above, a move does not disappear away one of the objects. Both a copy and move from one object to another will have two objects involved. The difference is what effect they have on the objects. A copy will of course copy the members of one object to the other. A move, on the other hand, will move the members from one object to another - typically a faster operation.
  2. N/A
Joseph Mansfield
  • 108,238
  • 20
  • 242
  • 324
  • So if my object has member pointers, and its destructor will release these pointers. Does that mean I can't really move those objects? – keelar Feb 13 '14 at 22:41
  • 1
    @keelar You can - just set the pointers to `nullptr` when you move from it. Doing `delete` on a null pointer will have no effect. When you implement a move constructor/assignment operator, you are supposed to leave the object in a valid (but indeterminate) state. – Joseph Mansfield Feb 13 '14 at 22:41
  • Thank you very much! That sounds perfect. Can I further know whether the `= default` move constructor / assignment will assign `nullptr` to the source member pointers? Or should I develop my own move constructor / assignment? – keelar Feb 13 '14 at 22:43
  • 1
    @keelar If your class is performing memory management, then you definitely need to implement the move constructor/assignment operator yourself. The implicitly defined move constructor will just perform a move on each of its members (as in, it will move construct the members of the new object from the members of the old object). This is known as the [rule of five](http://stackoverflow.com/q/4782757/150634). You can generally avoid having to do this, however, if you follow the [rule of zero](http://flamingdangerzone.com/cxx11/2012/08/15/rule-of-zero.html). – Joseph Mansfield Feb 13 '14 at 22:46
1

The move constructor steals attributes/members of an object and gives it to the new object. So in your example, the first set of delete statements occurs when the scope of the move constructor ends and the now empty object is destroyed.

And the second set of delete statements occur when the newly created objects inside the queue are destroyed

Also it is worth noting that if the attributes of the deleted object are not POD types, then it is not a good idea to access them in the delete method otherwise that would cause a seg fault

Community
  • 1
  • 1
smac89
  • 39,374
  • 15
  • 132
  • 179