Let's suppose that I have struct Foo
with move constructor
and operator=(Foo&&)
, and I used it as data member:
Foo f()
{
Foo foo;
//code
return foo;
}
struct Boo {
Foo foo;
Boo() {
foo = f();//1
foo = std::move(f());//2
}
};
In case (2) I actually not need std::move
,
but what if I used it here, does this make something bad,
like preventing optimization?
I read this: Why does std::move prevent RVO?
and find out that changing return foo;
to return std::move(foo);
cause disabling of RVO
, but what about (2) does it cause the similar situation? And if so, why?
It's redundant and confusing. Just because I can write std::add_pointer_t<void>
instead of void*
, or std::add_lvalue_reference_t<Foo>
(or Foo bitand
) instead of Foo&
, doesn't mean I should.
It also matters in other contexts:
auto&& a = f(); // OK, reference binding to a temporary extends its lifetime
auto&& b = std::move(f()); // dangling
and so, if Foo
is something that can be iterated over,
for(const auto& p : f()) {} // OK
for(const auto& p : std::move(f())) {} // UB
And in your example, if the assignment operator is implemented as copy-and-swap (operator=(Foo)
), then foo = std::move(f())
forces a non-elidable move, while foo = f()
can elide the move from f()
's return value to the argument of operator=
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With