为什么 defaulted-move-ctor 禁止隐式复制 ctor 但不禁止 defaulted-copy-ctor?

Why does defaulted-move-ctor inhibit implicit-copy-ctor but not defaulted-copy-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;
    ^

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

The implicitly-declared or defaulted copy constructor for class T is defined as deleted if any of the following conditions are true:
[...]
T has a user-defined move constructor or move assignment operator;

请注意,默认构造函数显然在此处算作 "user-declared"。 但是,如果我们现在删除第 4 行的注释,从而显式默认复制构造函数,程序将编译而不会出错,即使我上面引用的语句指定:

The implicitly-declared or defaulted copy constructor

这似乎是矛盾的。这是 cppreference 中的错误还是我只是混淆了?

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

Why does defaulted-move-ctor inhibit implicit-copy-ctor but not defaulted-copy-ctor?

因为当您将构造函数定义为默认构造函数时,您正在重新建立由移动构造函数引起的删除效果,默认复制构造函数与显式定义它执行编译器将执行的操作具有相同的效果。