Home > Back-end >  Moving a vector of unique_ptrs bug
Moving a vector of unique_ptrs bug

Time:08-19

I've always used std::move to move a std::vector into an empty one in member initialization lists like this:

class Bar{};

class Foo
{
public:
    Foo(std::vector<std::unique_ptr<Bar>>&& t_values)
        : m_Values{ std::move(t_values) }
    {
    }

private:
    std::vector<std::unique_ptr<Bar>> m_Values{};
};

I thought that the std::move in the constructor would clear the t_values vector, but recently I've discovered a bug that does not clear the t_values vector and causes unexpected behaviour e.g. destroying the vectors elements before they should be (std::swap would fix this issue). Is it not required by the standard for the moved vector to be empty?

CodePudding user response:

A move results in a "valid but unspecified state":

Moved-from state of library types                     [lib.types.movedfrom]

Objects of types defined in the C   standard library may be moved from.
Move operations may be explicitly specified or implicitly generated. Unless
otherwise specified, such moved-from objects shall be placed in a valid
but unspecified state.

A moved-from vector can certainly be empty, that would be "valid". But nothing in the C standard requires that. In the case of a moved-from vector of std::unique_ptrs, it would also be "valid" if the moved-from vector remains non-empty, but now has some indeterminate number of default-constructed std::unique_ptrs (the moved-from vector's size can remain the same, or may be different). The original std::unique_ptrs are now in the moved-to vector, and the moved-from vector has some default-constructed std::unique_ptrs. No rules are broken. The moved-from vector is in a "valid" state.

For various practical reasons, it's extremely unlikely for a moved-from vector in any typical C library implementation to behave this way, in this case. That's very unlikely. But it would be valid, if it were the case, provided that the overall state is still valid. It would not be valid for both the moved-from and the moved-to vector of std::unique_ptrs to end up with std::unique_ptrs to the same objects.

If you're observing spurious, or extra, object construction or destruction, it must be due to undefined behavior of some other source. There's nothing wrong with the shown code. If there's undefined behavior, it must be in code that's not shown.

  •  Tags:  
  • c
  • Related