当我编写"f5() = X(33);"
(当在注释行中移动构造函数时),编译器不会抛出错误。但是当我添加一个移动构造函数时,编译器说:
" 'X &X::operator =(const X &)': attempting to reference a deleted function "
是移动构造函数删除赋值运算符吗??
#include <iostream>
class X {
int* p;
public:
X(int ii = 0) { p = new int(ii); };
X(const X& obj) { this->p = new int(*(obj.p)); };
// X(X&& obj) { this->p = new int(*(obj.p)); delete obj.p; obj.p=nullptr;
};
X f5() {
return X(5);
}
int main() {
f5() = X(33);
system("pause");
}
发布于 2019-10-02 17:33:14
f5() = X(33);
将调用赋值运算符,因为那里已经存在一个X对象。这是一项任务,而不是建筑。在你有一个移动构造函数之前,它调用一个自动生成的赋值操作符。
现在,编译器不愿意(好吧,禁止)生成默认赋值操作符,因为您实现了一个移动构造函数。逻辑是这样的,你可能更了解你的类型,所以它会让你实现
X &X::operator =(const X &)
发布于 2019-10-02 17:48:25
错误消息('X &X::operator =(const X &)': function was implicitly deleted because 'X' has a user-defined move constructor
)清楚地回答了您的问题。但是您显然想知道C++中这条规则的动机。
该规则是在C++11中引入的(与移动语义一起),以强制执行“3/5规则”,即以下所有内容必须一起使用或根本不使用:
move constructor
(在某些情况下,可以省略移动或复制构造函数/赋值的aiir )。
同样,在定义复制构造函数时删除复制赋值运算符也是有意义的,但为了保持向后兼容性,2011年不能这样做。
您的代码很好地说明了为什么需要3/5规则。实际上,您的类会泄漏内存。如果你用delete p
添加一个析构函数,但没有定义一个移动赋值操作符,那么在你的例子中,你会得到一个双重删除(未定义的行为,可能会崩溃)。
最后,请注意您的移动构造函数是错误的。
https://stackoverflow.com/questions/58206303
复制相似问题