具有const和非const引用的C ++自动生成的副本构造函数

时间:2017-08-20 00:22:04

标签: c++ copy-constructor default-constructor

请考虑以下代码段:

#include <iostream>

struct Foo {
    Foo() = default;
    Foo(Foo &) {
        std::cout << "Foo(Foo &)" << std::endl;
    }
};

struct Bar { Foo m; };

int main() {
    Bar b;
    Bar b2(b);
}

如果运行此代码,则会写入 Foo(Foo&amp;)消息。好的,因为Foo没有Foo(const Foo &)构造函数,所以为Base(Base &)生成了Base构造函数。现在,如果我们将以下内容添加到Foo

的定义中
Foo(const Foo &) {
    std::cout << "Foo(const Foo &)" << std::endl;
}

将写入 Foo(const Foo&amp;)消息。好的,现在Foo具有带有const ref参数的copy-constructor,因此Base(const Base&amp;)由编译器生成。但是,如果我将Foo(const Foo &)声明为明确删除:

Foo(const Foo&) = delete;

然后程序将无法编译并出现以下错误:

prog.cc: In function 'int main()':
prog.cc:15:13: error: use of deleted function 'Bar::Bar(const Bar&)'
     Bar b2(b);
             ^
prog.cc:11:8: note: 'Bar::Bar(const Bar&)' is implicitly deleted because the default definition would be ill-formed:
 struct Bar { Foo m; };
        ^~~
prog.cc:11:8: error: use of deleted function 'Foo::Foo(const Foo&)'
prog.cc:8:5: note: declared here
     Foo(const Foo&) = delete;
     ^~~

在代码的第一个版本中,如果没有生成Foo(const Foo&),为什么我们不会出现错误,就像第三次修订一样?如果它被生成,为什么不调用它(不产生输出消息),就像在第二次修订中那样?

2 个答案:

答案 0 :(得分:2)

如果没有用户声明的copy-ctor,move-ctor或move-assignment-operator,则隐式声明并定义复制构造函数。

如果所有虚拟基地,直接基地和非静态数据成员X(const X&)声明接受T的复制者,则其格式为const T&。 否则它的格式为X(X&)

隐式声明的copy-ctor是默认的,如果默认定义(成员方式副本)格式错误,则删除默认的copy-ctor。

您收到错误,因为子对象copy-ctor接受const&amp;删除,使包含类copy-ctor删除。

答案 1 :(得分:0)

如果您将以下内容添加到您的代码中

Foo(const Foo&) = delete;

并试图用

打电话
 Bar b2(b);

您使用Foo(const Foo&) = delete;

进行编码
#include <iostream>

struct Foo {
    Foo() = default;
    Foo(const Foo&) = delete;

    Foo(Foo &) {
        std::cout << "Foo(Foo &)" << std::endl;
    }
};

struct Bar { Foo m; };

int main() {
    Bar b;
    Bar b2(b);
}
  

您正在尝试调用隐式删除的Bar

复制构造函数