我在尝试移动std::vector<T>
时遇到了崩溃T
显然无法移动(没有定义移动构造函数/赋值运算符,并且它包含内部指针)
但为什么vector的move函数想要调用T
的移动函数?它没有必要。
所以我的问题来自标题:如果std::vector<T>
不可移动,T
是否可以移动?
答案 0 :(得分:5)
n3797的[container.requirements.general]中关于“可识别分配器的容器要求”的表99说明移动构造:
要求:
A
的移动构造不会通过例外退出。
其中A
是分配器类型。它不需要 MoveInsertable 作为值类型。
时间复杂度要求是:“常数”,顺便说一句。
std::vector
通常存储一些指针和分配器。移动构造std::vector
时,只需移动指针和分配器。不需要触摸元素。
答案 1 :(得分:5)
是的,即使std::vector<T>
不可移动,T
也可以移动。左侧仅取得右侧矢量的所有权,不触及任何元素。 (有一个例外,列在#2中)
vector
的移动分配只会调用移动构造函数或移动T
的赋值,如果它们和它们的分配器比较相等而左侧的分配器的propagate_on_container_move_assignment
是false
。 (请注意,如果您的移动构造函数可能抛出或不存在,则将使用复制构造函数)但是,您不太可能遇到其中任何一个。
Reworded:如果propagate_on_container_move_assignment
是true
(通常是),则vector
始终可以移动,并且不会触及单个元素。如果它是false
,但分配器比较相等,则将移动向量而不触及单个元素。如果它是假的并且分配器比较不等,则将转移各个元素。如果存在nothrow移动分配,则使用该分配。否则,如果存在复制构造函数,则使用该复制构造函数。否则使用投掷移动分配。如果它既不可移动也不可复制,那就是未定义的行为。
T(T&&) = delete;
和T& operator=(T&&) =delete
,但我不建议这样做。相反,添加一个正确工作的移动构造函数并移动assignemnt。它们往往很简单,而且很有用。