显式定义的复制构造函数不会调用成员的复制构造函数。
当您进入构造函数的主体时,该类的每个成员都将被初始化。也就是说,一旦您到达 {
,则可以保证所有成员都已经被初始化。
除非另有规定,否则成员按它们出现在类中的顺序进行默认初始化。 (如果不能这样做,则程序无效。)因此,如果您定义自己的复制构造函数,现在就需要您根据需要调用任何成员复制构造函数。
以下是一个小程序,您可以将其复制粘贴到某个地方并随意更改:
#include <iostream>
class Foo {
public:
Foo() {
std::cout << "In Foo::Foo()" << std::endl;
}
Foo(const Foo& rhs) {
std::cout << "In Foo::Foo(const Foo&)" << std::endl;
}
};
class Bar {
public:
Bar() {
std::cout << "In Bar::Bar()" << std::endl;
}
Bar(const Bar& rhs) {
std::cout << "In Bar::Bar(const Bar&)" << std::endl;
}
};
class Baz {
public:
Foo foo;
Bar bar;
Baz() {
std::cout << "In Baz::Baz()" << std::endl;
}
Baz(const Baz& rhs) {
std::cout << "In Baz::Baz(const Baz&)" << std::endl;
}
};
int main() {
Baz baz1;
std::cout << "Copying..." << std::endl;
Baz baz2(baz1);
}
原样输出如下:
In Foo::Foo()
In Bar::Bar()
In Baz::Baz()
Copying...
In Foo::Foo()
In Bar::Bar()
In Baz::Baz(const Baz&)
请注意,这里是默认初始化了Baz
的成员。
如果注释掉显式复制构造函数,如下所示:
输出将是这样的:
在 Foo::Foo() 中
在 Bar::Bar() 中
在 Baz::Baz() 中
复制……
在 Foo::Foo(const Foo&) 中
在 Bar::Bar(const Bar&) 中
它会调用两个对象的复制构造函数。
如果我们重新引入
Baz
的复制构造函数并显式复制单个成员:
Baz(const Baz& rhs) :
foo(rhs.foo)
{
std::cout << "In Baz::Baz(const Baz&)" << std::endl;
}
我们得到:
在 Foo::Foo()
在 Bar::Bar()
在 Baz::Baz()
复制...
在 Foo::Foo(const Foo&)
在 Bar::Bar()
在 Baz::Baz(const Baz&)
如你所见,一旦你显式声明了一个复制构造函数,
你就要负责复制所有类成员;现在是你的构造函数。
这适用于所有构造函数,包括移动构造函数。