为什么使用std :: vector :: push_back的move变量会调用移动项的复制构造函数?

Tha*_*wen 2 c++ move vector

这里有一些代码无法编译,因为push_back试图在MoveOnlyClass中调用复制构造函数,该构造函数被删除:

class MoveOnlyClass
{
public:
    MoveOnlyClass() {};
    MoveOnlyClass& operator=(const MoveOnlyClass& other) = delete;
    MoveOnlyClass(const MoveOnlyClass& other) = delete;
};

int main()
{
    std::vector<MoveOnlyClass> vec;
    vec.push_back(std::move(MoveOnlyClass()));
}
Run Code Online (Sandbox Code Playgroud)

为什么会这样?当然,向量应该调用的唯一东西是移动构造函数.将对象移动到向量中的正确方法是什么?

Xir*_*ema 5

删除复制构造函数/复制赋值函数也会隐式删除move-constructor/move赋值函数.如果您打算使对象可移动但不可复制,则还需要default移动构造函数.

class MoveOnlyClass
{
public:
    MoveOnlyClass() {};
    MoveOnlyClass& operator=(const MoveOnlyClass& other) = delete;
    MoveOnlyClass(const MoveOnlyClass& other) = delete;
    MoveOnlyClass& operator=(MoveOnlyClass&& other) = default;
    MoveOnlyClass(MoveOnlyClass&& other) = default;
};

//Will now compile as you expect
int main()
{
    std::vector<MoveOnlyClass> vec;
    vec.push_back(std::move(MoveOnlyClass()));
}
Run Code Online (Sandbox Code Playgroud)

而且,std::move(T())多余; 像这样就地构造一个对象已经使它成为一个R值,并且std::move当你不需要时使用它可能会阻止某些类型的编译器优化(比如Copy Ellision).

  • 我建议使用`emplace_back`而不是`push_back` (4认同)
  • 对于`std :: is_move_assignable`和`std :: is_move_constructible`的`<type_traits>`可能是有意义的,以编程方式验证目标类对象是否具有所需的特征. (2认同)