为什么默认的移动ctor禁止隐式复制ctor而不禁止默认的复制ctor



我似乎遇到了一个例子,其中默认的移动构造函数似乎根据情况同时算作用户声明和非用户声明:

struct Foo {
int a;
Foo():a(42){};
//Foo(const Foo & other) = default;
Foo(Foo && other) = default;
};
int main() {
Foo f;
Foo g = f;
}

结果如下:

test.cpp:11:9: error: call to implicitly-deleted copy constructor of 'Foo'
Foo g = f;
^   ~
test.cpp:5:5: note: copy constructor is implicitly deleted because 'Foo' has a user-declared move constructor
Foo(Foo && other) = default;
^

编译器错误是意料之中的,因为cpprreference告诉我们:

类T的隐式声明或默认复制构造函数是如果以下任何条件成立,则定义为已删除:
[…]
T具有用户定义的移动构造函数或移动赋值运算符;

注意,默认构造函数在这里显然算作"用户声明的"。然而,如果我们现在从第4行中删除注释,从而显式地默认复制构造函数,则程序将编译无错误,即使我上面引用的语句指定:

隐式声明的或默认的复制构造函数

这似乎是一个矛盾。这是cpprreference中的错误,还是我只是感到困惑?

这看起来像是cppreference的一个错误。声明移动构造函数/赋值运算符只会隐式删除声明的复制构造函数。事实上,将复制构造函数声明为默认构造函数就是用户声明它,因此这不适用于这种情况。

为什么默认的移动ctor禁止隐式复制ctor而不禁止默认的复制ctor?

因为当你将构造函数定义为默认构造函数时,你正在重新建立由移动构造函数引起的删除效果,默认复制构造函数的效果与明确定义它做编译器会做的事情相同。

最新更新