Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it undesirable to defensively apply std::move to trivially-copyable types?

Tags:

c++

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?

like image 610
Disenchanted Avatar asked Mar 12 '18 17:03

Disenchanted


People also ask

What does trivially copyable mean?

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.

Is STD array trivially copyable?

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.

What happens during std :: move?

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.


1 Answers

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.

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.

like image 187
Vittorio Romeo Avatar answered Oct 22 '22 01:10

Vittorio Romeo