Is it safe to call size() method on moved-from vector? [duplicate]
Asked Answered
W

1

7

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?

Winna answered 12/7, 2019 at 13:53 Comment(4)
To see what preconditions a standard container function/operation has see: timsong-cpp.github.io/cppwp/container.requirementsHooves
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.Embody
@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?Winna
@Winna 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.Embody
P
9

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.

Prajna answered 12/7, 2019 at 13:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.