Yes,
std::vector<T>
is movable even ifT
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 ofT
if the and their allocators compare as equal and the left side's allocator'spropagate_on_container_move_assignment
isfalse
. (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
istrue
(it usually is), then thevector
is always movable, and does so without touching individual elements. If it'sfalse
, 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.- 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;
andT& 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.
Is a std::vector<T> movable if T is not movable?
-
01-07-2023 - |
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?
Solution
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.