代码之家  ›  专栏  ›  技术社区  ›  Tharwen Jorge Israel Peña

为什么使用std::vector::push\u back的move变量调用移动项的复制构造函数?

  •  2
  • Tharwen Jorge Israel Peña  · 技术社区  · 6 年前

    以下是一些无法编译的代码,因为push\u 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()));
    }
    

    2 回复  |  直到 6 年前
        1
  •  5
  •   Xirema    6 年前

    删除复制构造函数/复制赋值函数也会隐式删除移动构造函数/移动赋值函数。如果要使对象可移动但不可复制,还需要 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()));
    }
    

    std::move(T()) std::move 当您不需要时,可能会阻止某些类型的编译器优化(如复制省略)。

        2
  •  2
  •   Community CDub    5 年前

    我只想用语言规范的适当摘录来支持它,使事情变得正式。所以从 [class.copy.ctor¶8]

    (8) 如果类X的定义没有显式声明move构造函数,则非显式构造函数将隐式声明为default

    • (8.1) X没有用户声明的复制构造函数 ,

    为此,我们应该添加声明为已删除仍然是声明。因此,根据这一点,我们没有得到 在你的情况下,因为我们已经有了 用户声明的复制构造函数

    此外,根据 [dcl.fct.def.delete¶3] :

    一个人可以使一个类不可复制, i、 例如,仅移动,使用deleted 和 然后提供move构造函数和move 赋值运算符。