Reputation: 9292
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?
Upvotes: 7
Views: 2661
Reputation: 66932
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)
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.
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.Upvotes: 10
Reputation: 39121
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.
Upvotes: 8