c – 默认移动构造函数/赋值和已删除的复制构造函数/赋值
作者:互联网
根据标准,
If the definition of a class X does not explicitly declare a move constructor, one will be implicitly declared as defaulted if and only if
— X does not have a user-declared copy constructor,
— X does not have a user-declared copy assignment operator,
— X does not have a user-declared move assignment operator, and
— X does not have a user-declared destructor.
现在以下无法编译
# include <utility>
class Foo
{
public:
Foo() = default;
Foo(Foo const &) = delete;
};
int main()
{
Foo f;
Foo g(std::move(f)); // compilation fails here
return 0;
}
所以似乎删除的函数被认为是用户定义的,这是有道理的(它不是它的默认实现).但是,在那种特殊情况下,如何删除复制construtor / assignment mess默认移动构造函数/赋值?
我认为这个问题具有实际意义,因为手动生成和特别是维护这样的默认函数是容易出错的,同时,使用诸如std :: unique_ptr这样的类作为类成员的(正当)增加使得不可复制的类比以前更常见的类.
解决方法:
用户声明表示用户提供(由用户定义),显式默认(=默认)或显式删除(=删除),与隐式默认/删除(例如移动构造函数)相反.
因此,在您的情况下,是隐式删除移动构造函数,因为复制构造函数被显式删除(因此用户声明).
However, in that particular case, how would deleted copy constructor/assignment mess default move constructor/assignment?
它不会,但标准并没有区分这种情况和复杂的情况.
最简单的答案是,在某些情况下,拥有一个带有显式删除的拷贝构造函数的隐式定义的移动构造函数可能是危险的,当你有一个用户定义的析构函数而没有用户定义的拷贝构造函数时(见rule of three/five/zero)也是如此.现在,您可以争辩说用户定义的析构函数不会删除复制构造函数,但这只是语言中的一个缺陷,无法删除,因为它会破坏很多旧的(坏的)程序.引用Bjarne Stroustrup:
In an ideal world, I think we would decide on “no generation” as the default and provide a really simple notation for “give me all the usual operations.” […] Also, a “no default operations” policy leads to compile time errors (which we should have an easy way to fix), whereas a generate operations by default policy leads to problems that cannot be detected until run time.
您可以在N3174=10-0164了解更多相关信息.
请注意,大多数人都遵循rule of three/five/zero,在我看来你应该这样做.通过隐式删除默认的move-constructor,标准是“保护”你免于错误,并且在某些情况下应该通过删除copy-constructor来保护你很长时间(参见Bjarne的论文).
如果您有兴趣,请进一步阅读:
> Enforcing the Rule of Zero
> N3153 – Implicit Move Must Go
> N3174
> N3201
I think this question has practical importance because manual generation and esp. maintenance of such default functions is error prone, while at the same time, the (righteous) increase of the use of classes such as
std::unique_ptr
as class members made non-copyable classes much more common beasts than they used to be.
将移动构造函数标记为显式默认将解决此问题:
class Foo {
public:
Foo() = default;
Foo(Foo const &) = delete;
Foo(Foo&&) = default;
};
你得到一个带有默认移动构造函数的不可复制对象,在我看来,这些显式声明优于隐式声明(例如,只是将移动构造函数声明为默认值而不删除复制构造函数).
标签:c,move-semantics,deleted-functions 来源: https://codeday.me/bug/20190923/1815766.html