Question

I am getting a crash when trying to move a std::vector<T> where T is clearly not movable (no move constructor/assignment operator was defined, and it contains internal pointers)

But why would the move functions of vector want to call the move functions of T? It should not be necessary.

So my question from the title: Is a std::vector<T> movable if T is not movable?

Was it helpful?

Solution

  1. Yes, std::vector<T> is movable even if T is not movable. The left side merely takes ownership from the vector on the right, no elements are touched. (With one exception, listed in #2)

  2. The move assignment of a vector would only call the move constructor or move assignment of T if the and their allocators compare as equal and the left side's allocator's propagate_on_container_move_assignment is false. (Note that if your move constructor might throw or doesn't exist, the copy constructor will be used instead) However, it is unlikely that you are encountering either of these.

    Reworded: if propagate_on_container_move_assignment is true (it usually is), then the vector is always movable, and does so without touching individual elements. If it's false, but the allocators compare equal, the vector will be moved without touching individual elements. If it's false and the allocators compare inequal, the individual elements will be transferred. If a nothrow move assignment exists, that's used. Otherwise, if a copy constructor exists, that's used. Otherwise the throwing move assignment is used. If it's neither movable nor copiable, then that's undefined behavior.

  3. Having no move assignment operator defined, and the class containing internal pointers, does not mean your class is not movable. In fact, it sounds like the compiler thinks it is movable. If you want to disable moves, use T(T&&) = delete; and T& operator=(T&&) =delete, but I don't recommend that. Instead, add a correctly working move constructor and move assignemnt. They tend to be easy, and quite useful.

OTHER TIPS

Table 99 in [container.requirements.general] of n3797 about "Allocator-aware container requirements" says about move construction:

Requires: move construction of A shall not exit via an exception.

Where A is the allocator type. It does not require MoveInsertable for the value type.

The time complexity requirement is: "constant", btw.


std::vector typically stores some pointers plus the allocator. When move-constructing a std::vector, only pointers and the allocator have to be moved. The elements don't need to be touched.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top