请考虑以下代码段:
#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&)
,为什么我们不会出现错误,就像第三次修订一样?如果它被生成,为什么不调用它(不产生输出消息),就像在第二次修订中那样?
答案 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
复制构造函数