次のコードを検討してください。
#include <vector>
#include <iostream>
using namespace std;
class Base
{
char _type;
public:
Base(char type):
_type(type)
{}
~Base() {
cout << "Base destructor: " << _type << endl;
}
};
class uncopyable
{
protected:
uncopyable() {}
~uncopyable() {}
private:
uncopyable( const uncopyable& );
const uncopyable& operator=( const uncopyable& );
};
class Child : public Base, private uncopyable
{
int j;
public:
Child():
Base('c')
{}
~Child() {
cout << "Child destructor" << endl;
}
};
int main()
{
vector<Base> v;
Base b('b');
Child c;
v.push_back(b);
v.push_back(c);
return 0;
}
私のシステムの出力は次のとおりです。
Base destructor: b
Child destructor
Base destructor: c
Base destructor: b
Base destructor: b
Base destructor: c
私の質問は次のとおりです。
(型 bの) のデストラクタが
Base
2 回ではなく 3 回呼び出されるのはなぜですか (オブジェクト b のコピーが 2 つ以上あるのでしょうか)。Child
親の 1 つのコピー コンストラクターがプライベートであることを考慮して、type のオブジェクトをコピーするとどうなりますか。未定義の動作ですか?type のオブジェクトをコピーしようとすると、コンパイル時にエラーが発生することを期待していました
Child
。子のデフォルトのコピー コンストラクターが Uncopyable クラスのプライベート コピー コンストラクターを呼び出そうとすると、コンパイル エラーが発生すると思いました。コンパイルエラーが発生しないのはなぜですか?
コードがこのように設計されている理由は、Child
クラスが巨大だからです。
Child
望ましい動作は、クライアントがオブジェクトをコピーしようとするたびに子データを破棄することです ( のデストラクタChild
を呼び出さずに のデストラクタを呼び出しBase
ます)。
このコードはそれを実現しますが、未定義の動作が発生し、メモリリークが発生すると思います (Child
コピーされたインスタンスのデストラクタを呼び出すことはありません)。