Imagine we have a trivially-copyable type:
struct Trivial
{
float A{};
int B{};
}
which gets constructed and stored in an std::vector
:
class ClientCode
{
std::vector<Trivial> storage{};
...
void some_function()
{
...
Trivial t{};
fill_trivial_from_some_api(t, other_args);
storage.push_back(std::move(t)); // Redundant std::move.
...
}
}
Normally, this is a pointless operation, as the object will be copied anyway.
However, an advantage of keeping the std::move
call is that if the Trivial
type would be changed to no longer be trivially-copyable, the client code will not silently perform an extra copy operation, but a more appropriate move. (The situation is quite possible in my scenario, where the trivial type is used for managing external resources.)
So my question is whether there any technical downsides to applying the redundant std::move
?
A trivially copyable class is a class that: has no non-trivial copy constructors, has no non-trivial move constructors, has no non-trivial copy assignment operators, has no non-trivial move assignment operators, and has a trivial destructor.
std::array however, has a static size set at compile time. It does not have internal pointers and can therefore be copied simply by using memcpy . It therefore is trivial to copy.
std::move is used to indicate that an object t may be "moved from", i.e. allowing the efficient transfer of resources from t to another object. In particular, std::move produces an xvalue expression that identifies its argument t . It is exactly equivalent to a static_cast to an rvalue reference type.
However, an advantage of keeping the
std::move
call is that if theTrivial
type would be changed to no longer be trivially-copyable, the client code will not silently perform an extra copy operation, but a more appropriate move.
This is correct and something you should think about.
So my question is whether there any technical downsides to applying the redundant
std::move
?
Depends on where the moved object is being consumed. In the case of push_back
, everything is fine, as push_back
has both const T&
and T&&
overloads that behave intuitively.
Imagine another function that had a T&&
overload that has completely different behavior from const T&
: the semantics of your code will change with std::move
.
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