明示的に定義されたコピー コンストラクターは、メンバーのコピー コンストラクターを呼び出しません。
コンストラクターの本体に入ると、そのクラスのすべてのメンバーが初期化されます。つまり、一度到達する{
と、すべてのメンバーが初期化されていることが保証されます。
指定しない限り、メンバーはクラスに表示される順序でデフォルトで初期化されます。(そして、そうできない場合、プログラムの形式が正しくありません。) したがって、独自のコピー コンストラクターを定義する場合、任意のメンバー コピー コンストラクターを必要に応じて呼び出すのはあなた次第です。
これは、どこかにコピーして貼り付けていじることができる小さなプログラムです。
#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);
}
現状では、これは以下を出力します:
Foo::Foo() で
In Bar::Bar()
Baz::Baz() で
コピー中...
Foo::Foo() で
In Bar::Bar()
In Baz::Baz(const Baz&)
のメンバーをデフォルトで初期化していることに注意してくださいBaz
。
次のように、明示的なコピー コンストラクターをコメント アウトします。
/*
Baz(const Baz& rhs) {
std::cout << "In Baz::Baz(const Baz&)" << std::endl;
}
*/
出力は次のようになります。
Foo::Foo() で
In Bar::Bar()
Baz::Baz() で
コピー中...
Foo::Foo(const Foo&) で
In Bar::Bar(const Bar&)
両方でコピー コンストラクターを呼び出します。
そして、Baz
のコピー コンストラクターを再導入し、単一のメンバーを明示的にコピーすると、次のようになります。
Baz(const Baz& rhs) :
foo(rhs.foo)
{
std::cout << "In Baz::Baz(const Baz&)" << std::endl;
}
我々が得る:
Foo::Foo() で
In Bar::Bar()
Baz::Baz() で
コピー中...
Foo::Foo(const Foo&) で
In Bar::Bar()
In Baz::Baz(const Baz&)
ご覧のとおり、コピー コンストラクターを明示的に宣言すると、すべてのクラス メンバーのコピーを担当します。それは今あなたのコンストラクタです。
これは、移動コンストラクターを含むすべてのコンストラクターに適用されます。