如果T不可移动,std :: vector <t>是否可移动?</t>

时间:2014-04-10 17:57:15

标签: c++ c++11 vector move-semantics

我在尝试移动std::vector<T>时遇到了崩溃T显然无法移动(没有定义移动构造函数/赋值运算符,并且它包含内部指针)

但为什么vector的move函数想要调用T的移动函数?它没有必要。

所以我的问题来自标题:如果std::vector<T>不可移动,T是否可以移动?

2 个答案:

答案 0 :(得分:5)

n3797的[container.requirements.general]中关于“可识别分配器的容器要求”的表99说明移动构造:

  

要求: A的移动构造不会通过例外退出。

其中A是分配器类型。它不需要 MoveInsertable 作为值类型。

时间复杂度要求是:“常数”,顺便说一句。


std::vector通常存储一些指针和分配器。移动构造std::vector时,只需移动指针和分配器。不需要触摸元素。

答案 1 :(得分:5)

  1. 是的,即使std::vector<T>不可移动,T也可以移动。左侧仅取得右侧矢量的所有权,不触及任何元素。 (有一个例外,列在#2中)

  2. vector的移动分配只会调用移动构造函数或移动T的赋值,如果它们和它们的分配器比较相等而左侧的分配器的propagate_on_container_move_assignmentfalse。 (请注意,如果您的移动构造函数可能抛出或不存在,则将使用复制构造函数)但是,您不太可能遇到其中任何一个。

    Reworded:如果propagate_on_container_move_assignmenttrue(通常是),则vector始终可以移动,并且不会触及单个元素。如果它是false,但分配器比较相等,则将移动向量而不触及单个元素。如果它是假的并且分配器比较不等,则将转移各个元素。如果存在nothrow移动分配,则使用该分配。否则,如果存在复制构造函数,则使用该复制构造函数。否则使用投掷移动分配。如果它既不可移动也不可复制,那就是未定义的行为。

  3. 没有定义移动赋值运算符,并且包含内部指针的类确实意味着您的类不可移动。事实上,这听起来像编译器认为它 可移动。如果您要禁用移动,请使用T(T&&) = delete;T& operator=(T&&) =delete,但我不建议这样做。相反,添加一个正确工作的移动构造函数并移动assignemnt。它们往往很简单,而且很有用。