Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/127.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么使用std::vector::push#u back的move变量调用移动的项';复制构造函数是什么?_C++_Vector_Move - Fatal编程技术网

C++ 为什么使用std::vector::push#u back的move变量调用移动的项';复制构造函数是什么?

C++ 为什么使用std::vector::push#u back的move变量调用移动的项';复制构造函数是什么?,c++,vector,move,C++,Vector,Move,以下是一些无法编译的代码,因为push_back正在尝试调用MoveOnlyClass中的复制构造函数,该构造函数已被删除: class MoveOnlyClass { public: MoveOnlyClass() {}; MoveOnlyClass& operator=(const MoveOnlyClass& other) = delete; MoveOnlyClass(const MoveOnlyClass& other) = delete

以下是一些无法编译的代码,因为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()));
}
类MoveOnlyClass
{
公众:
MoveOnlyClass(){};
MoveOnlyClass和运算符=(常量MoveOnlyClass和其他)=删除;
MoveOnlyClass(常量MoveOnlyClass&其他)=删除;
};
int main()
{
std::vec;
向量推回(std::move(MoveOnlyClass());
}

为什么会发生这种情况?当然,向量唯一应该调用的是move构造函数。将对象移动到向量中的正确方法是什么?

删除复制构造函数/复制赋值函数也会隐式删除移动构造函数/移动赋值函数。如果要使对象可移动但不可复制,还需要
default
move构造函数

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()));
}
类MoveOnlyClass
{
公众:
MoveOnlyClass(){};
MoveOnlyClass和运算符=(常量MoveOnlyClass和其他)=删除;
MoveOnlyClass(常量MoveOnlyClass&其他)=删除;
MoveOnlyClass和运算符=(MoveOnlyClass和其他)=默认值;
MoveOnlyClass(MoveOnlyClass&&other)=默认值;
};
//现在将按预期编译
int main()
{
std::vec;
向量推回(std::move(MoveOnlyClass());
}

而且,
std::move(T())
是冗余的;在这样的地方构造一个对象已经使它成为一个R值,并且在不需要的时候使用
std::move
可能会阻止某些类型的编译器优化(比如复制省略)。

由@Xirema给出的答案确定了代码中的问题,并解释了为什么会出现这种情况

我只是想用语言规范的适当摘录来支持它,使事情正式化。因此,来自:

(8) 如果类X的定义没有显式声明移动构造函数,则非显式构造函数将隐式声明为默认当且仅当

  • (8.1)X没有用户声明的复制构造函数
为此,我们应该添加声明为已删除仍然是声明。因此,根据这一点,在您的情况下,我们不会得到隐式声明的move构造函数,因为我们已经有了一个用户声明的copy构造函数

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()));
}
此外,根据:

可以使用deleted使类不可复制,即仅移动 复制构造函数和复制赋值运算符的定义,和 然后提供move构造函数和move的默认定义 分配操作员。


该类没有move构造函数,最好包含错误消息。它通常会给出一个提示wrong@user463035818对。我在写这个例子时没有考虑到这一点。我的反对票是不支持任何研究。您可以通过
=default
添加移动构造函数,或者花2分钟检查编译器在什么条件下生成移动构造函数,而不是假设存在移动构造函数。没有什么私事,一票否决不会伤害到任何人,我相信其他人会发现这是不可能的,我坚持我的决定;)可能值得添加:如果类同时具有复制构造函数和移动构造函数,但移动构造函数未声明为
noexcept
,则
std::vector
将使用复制构造函数。(但是默认的移动构造函数会自动
noexcept
,如果合适的话。)@JeJo
std::vector
如果其对象不可复制,仍然可以调整自身大小。只有不可移动的对象才会出现这种问题。我建议
emplace\u back
而不是
push\u back
对于
std::is\u move\u assignable
std::is\u move\u constructible
可能会感兴趣,以编程方式验证目标类对象是否具有所需的特征。如果有移动构造函数和移动赋值运算符,则最好标记它们。