4

Standard specifies that STL containers, after begin moved (in this case we talk about std::move that enables move construction / assignment), are in valid, but unspecified state.

I belive that means we can only apply operations that require no preconditions. I recall that someone here, on Stackoverflow, claimed that to be true and after some checking I agreed. Unfortunately, I cannot recall what sources have I checked. Furthermore, I was not able to find relevant information in the standard.

From [container.requirements.general/4], table 62 ([tab:container.req]), we can see that a.size() has no preconditions. Does that mean this code is safe?

#include <iostream>
#include <vector>

int main() {
    std::vector<int> v1 = {1, 2, 3};
    std::vector<int> v2 = std::move(v1);

    std::cout << v1.size(); // displaying size of the moved-from vector
}

It's unspecified what will this code print, but is it safe? Meaning, do we have undefined behaviour here?

EDIT: I don't believe this question will be too broad if I ask abour other containers. Will the answer be consistent among all other STL containers, including std::string?

Fureeish
  • 9,869
  • 3
  • 23
  • 46
  • 1
    To see what preconditions a standard container function/operation has see: https://timsong-cpp.github.io/cppwp/container.requirements – NathanOliver Jul 12 '19 at 13:59
  • As an aside, there is no practical way for `.size()` to return anything except `0` here: the requirements on `vector( vector&& )` are such that *in the general case*, the buffer *must* be moved to the target vector, and the source vector cannot hold onto anything and must be empty. However, an insane std library might be able to justify doing something different, especially for a vector of PODs. – Yakk - Adam Nevraumont Jul 12 '19 at 14:08
  • @Yakk-AdamNevraumont so it's illegal for `vector(vector&& arg)` to simply call the relevant `swap(*this, arg)`? Where does it say that the moved-from vector must be empty? – Fureeish Jul 12 '19 at 14:15
  • @Fureeish This isn't `operator=`, it is move-construction. There is nothing in the "destination" vector to swap out of. Extra allocations can (in general) be observed; so cannot occur. There are insane ways to get around this, but not in general. – Yakk - Adam Nevraumont Jul 12 '19 at 14:20

1 Answers1

7

There is no undefined behavior here, because of the lack of pre-conditions. The Standard guarantees that a moved-from container will be left in a valid but unspecified state. A valid state implies that anything that doesn't have preconditions can be invoked, but the result will be unpredictable.

So yeah, this is not UB, but definitely useless and a bad idea.

Vittorio Romeo
  • 82,972
  • 25
  • 221
  • 369