2

Reading through the reference of Copy assignment operator, i noticed that it suggests copy-and-swap idiom when it comes to the first option of the operator signature:

class-name & class-name :: operator= ( class-name )

And later on the same page the sample implementation is given as follows:

A& operator=(A other)
{
    std::cout << "copy assignment of A\n";
    std::swap(n, other.n);
    std::swap(s1, other.s1);
    return *this;
}

At this point I started to wonder why this implementation is swapping the values with the temporary instead of just moving them out of it? Moreover, I decided to inspect more carefully this excellent SO answer regarding copy-and-swap idiom and noticed that it not only suggests the same approach, but also swaps values with an rvalue reference in another snippet (which is also is not required to keep original values at the end of the scope):

dumb_array(dumb_array&& other) noexcept ††
    : dumb_array() // initialize via default constructor, C++11 only
{
    swap(*this, other);
}

This is not the first time I witness that swapping is used with the values which are supposed to be destructed at the end of the given scope, however I struggle to see any benefits over using std::move with the "temporary" instead:

A& operator=(A other)
{
    std::cout << "copy assignment of A\n";
    n = std::move(other.n);
    s1 = std::move(other.s1);
    return *this;
}
The Dreams Wind
  • 8,416
  • 2
  • 19
  • 49
  • Your move is not the same thing as a swap. Please reread what `swap` does, then ask yourself if you'll get the same results with your move. – Sam Varshavchik Jul 26 '22 at 10:39
  • @SamVarshavchik I might not implement it properly, or it could not be the right types for such kind of operation, but in context of swapping even Stroustrup consider it a viable option in his "A Tour of C++" / **13.2.2 `move()` and `forward()`** (despite saying that `std::move` is better avoided for almost anything else). This, however, requires the given classes to have move constructor and move assignment implemented. – The Dreams Wind Jul 26 '22 at 10:47
  • 2
    A move is not a swap. If `T`'s destructor `delete`s `m_Array`, guess what happens as a result of `mArray = std::move(other.mArray);`? You now have two objects with the same `mArray` pointer (and a memory leak as a cherry on top). Good luck with your destructor's quest. A move is not a swap, no matter what attribtues it has. – Sam Varshavchik Jul 26 '22 at 10:50
  • 1
    @SamVarshavchik fair point, but let's assume it's not an array, but just `std::string`. (This is actually how the class is structured under the first link, it has `int` and `std::string` members) – The Dreams Wind Jul 26 '22 at 10:56
  • Then it will work, but slightly less efficiently. Using a move, rather than a move-based swap, will result in an extra allocation and deallocation (unless the strings are short-optimized). – Sam Varshavchik Jul 26 '22 at 10:59
  • 2
    @TheDreamsWind you shouldn't be writing the `operator=` for a class if move assigning each member is correct, because that's what the default does. – Caleth Jul 26 '22 at 11:05
  • 1
    @SamVarshavchik but is `std::swap` move-based? Also i'm not quite following why second example should cause extra allocation/deallocation if we compare it to `std::swap` which introduces extra temporary by contract – The Dreams Wind Jul 26 '22 at 11:07
  • @TheDreamsWind The C++ rule is that the moved from object should be valid. If instances need resources swap is a crafty way of ensuring the moved to object has the value of from and the from object is valid (being what the moved to object was). Think about a simple `vector` like class that doesn't use `nullptr` for empty. – Persixty Jul 26 '22 at 12:07
  • 2
    Similar question: [c++ - Copy & Move Idiom? - Stack Overflow](https://stackoverflow.com/questions/43368422/copy-move-idiom) – krisz Jul 26 '22 at 13:32

0 Answers0