johnbakers
johnbakers

Reputation: 24750

Using std::move inside a move constructor

This answer writes a move constructor like this:

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

Note: this swap is a custom swap also defined on the class, not std::swap.

This answer suggests that use of std::move:

you should only call std::move where appropriate, but this is were personal preferences come in.

I just watched a Scott Meyers talk on move semantics where he stated that an rvalue reference as a function parameter is turned back into an lvalue by virtue of the fact that it is now named, and therefore std::move is necessary once again turn it back into an rvalue.

In other words, the code above may very well not be doing a move operation, and that, unlike the quote above, use of std::move in such contexts is not about personal preference but about actually gaining benefits of move semantics.

Is it accurate to say then that if std::move is not explicitly used inside a move constructor or a move assignment operator, moving is probably not actually happening, and instead a copy is being done?

Upvotes: 3

Views: 544

Answers (2)

Aaron McDaid
Aaron McDaid

Reputation: 27133

I just watched a Scott Meyers talk on move semantics where he stated that an rvalue reference as a function parameter is turned back into an lvalue by virtue of the fact that it is now named, and therefore std::move is necessary once again turn it back into an rvalue.

That's correct.

But there are many misconceptions around this topic.

In other words, the code above may very well not be doing a move operation

It won't do a move. However, it's likely that swap is an efficient operation anyway and therefore you don't care.

use of std::move in such contexts is [...] about actually gaining benefits of move semantics.

Not true. Even if you use std::move, there is no guarantee that any moving will occur.

Is it accurate to say then that if std::move is not explicitly used inside a move constructor or a move assignment operator, moving is probably not actually happening, and instead a copy is being done?

moving can occur, even if there is no std::move.

So basically, std::move is neither necessary, nor sufficient, for moving to occur. This may seem quite surprising.


I think there is really no shortcut to this. If you want to understand this, find a good comprehensive tutorial. E.g. The popular C++ Rvalue References Explained by Thomas Becker.

Upvotes: 1

Is it accurate to say then that if std::move is not explicitly used inside a move constructor or a move assignment operator, moving is probably not actually happening, and instead a copy is being done?

No, that is most certainly not accurate. In the particular case in the question, it fully depends on the implementation of swap.

A natural implementation would be swap(dumb_array&, dumb_array&) which internally swaps some pointers, perhaps like this:

void swap(dumb_array &lhs, dumb_array &rhs)
{
  std::swap(lhs.pointer_to_data, rhs.pointer_to_data);
}

If that is the case, then the move constructor you've shown certainly performs a lightweight move—just a pointer swap. Second, using std::move when calling swap would be downright wrong, as swap takes lvalue references.

Upvotes: 4

Related Questions