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?
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.
std::array is movable only if its contained objects are movable. std::array is quite different from the other containers because the container object contains the storage, not just pointers into the heap. Moving a std::vector only copies some pointers, and the contained objects are none the wiser.
You can't move elements from one vector to another the way you are thinking about; you will always have to erase the element positions from the first vector. If you want to change all the elements from the first vector into the second and vice versa you can use swap.
No. It doesn't call the move constructor. To call move constructor of element you will have to call std::move while pushing to vector itself.
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.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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With