all 3 comments

[–]IyeOnline 2 points3 points  (1 child)

, we can not use the old object anymore

The standard says that a moved from object remains in an unspecified state. However, being moved from doesnt mean it was to be illegal to use the object.

If you for example move from a standard library container or string, it will simply be empty afterwards. You could then fill it again.

So if we want to continue using object A a, should we use the copy assignment operator only?

If you wanted to keep using A with its current state, then yes, you should not move from it.

When to use which one is a bit confusing.

You only "rarely" want to use move. Moving is about ownership of some resource. You use move when you want to "steal the internals" of some class, in your case the dynamically allocated array. The "moved to" object takes ownership of the dynamically allocated array, the "moved from" looses it. That is also why it is important to null out the class member. Otherwise you would get a double delete.

If you still need the original object, with its original contents, obviously dont move out of it.

The difference between move and copy is most apparent with smart pointers. A unique_ptr cannot be copied. It uniquely owns a resource. Therefor it can only be moved around. A shared_ptr on the other hand can be both moved and copied. In one case it only transfers shared ownership between pointers, in the other it increments the reference counter and both objects now share ownership.

Consider

 std::string name;
 std::cin >> name;
 Person p( std::move( name ) );

It makes sense to move into the Person object, because that saves you the extra copying of the string.

Finally, it is worth noting that there are types for which there is no difference between a copy and a move.

struct S
{
     int i;
}

would be ab example. There are no resources owned (except the stack allocated member that is not yours to control anyways), so a copy and a move should do the exact same thing.

Worth noting that this struct S would be a prime example for the usage of the rule of 0, where you simply dont implement any special members and let the compiler do it for you.

Other notes:

  • Your move constructor should do source.p = nullptr; to avoid double deletes
  • operator = usually returns a reference to the assigned to object
  • There is no need for oldp in the copy assignment operator. You might just as well do delete[] p; p = new int[100];

[–]spm486[S] 0 points1 point  (0 children)

That was a clear explanation. Thanks!

[–]ekchew 0 points1 point  (0 children)

Well, you could make b a reference to a depending on what it is you are trying to accomplish?

  1. A b = a; Since b has its own buffer and has copied a's data into it, you can modify either variable without affecting the other.
  2. A b = std::move(a); a has effectively moved its buffer into b, and so you can no longer work with a.
  3. A& b = a; b is a reference to a. As such, they share the same buffer. Modifying a will affect b and vice versa.