Представьте, что у вас есть класс, подобный такому, который демонстрирует проблему, которую вы задали в вопросе
class Foo{};
class Bar
{
public:
Foo* mFoo;
Bar() : mFoo( new Foo() ) {}
~Bar() { delete mFoo;}
};
И такой код
Bar x ;
Bar y = x;
Приведенный выше код вызовет дамп ядрапотому что и y, и x будут указывать на один и тот же Foo , а деструктор попытается удалить один и тот же Foo дважды.
ALTERNATIVE 1
Объявлять, но не предоставлять определение, чтобы Bar никогда не копировал конструктор и не назначал его.Это гарантирует, что Bar y = x
будет иметь ошибку связи, так как вы спроектировали класс, который не будет копироваться.
class Bar
{
public:
Foo* mFoo;
Bar() : mFoo( new Foo() ) {}
~Bar() { delete mFoo;}
Bar(const Bar &);
Bar& operator= (const Bar &);
};
ALTERNATIVE 2
Предоставьте конструктор копирования иоператор присваивания, который делает правильную вещь.Вместо того, чтобы компилятор предоставил реализацию по умолчанию копирования и присваивания, которые делают поверхностное копирование, вы дублируете Foo , чтобы и x, и y имели свои собственные Foo
class Bar
{
public:
Foo* mFoo;
Bar() : mFoo( new Foo() ) {}
~Bar() { delete mFoo;}
Bar(const Bar & src)
{
mFoo = new Foo( *(src.mFoo) );
}
Bar& operator= (const Bar & src)
{
mFoo = new Foo( *(src.mFoo) );
return *this;
}
};
ALTERNATIVE 3 (BEST)
Используйте C ++ 11 shared_ptr или boost и опустите копирование и присвоение в качестве компилятора по умолчанию, при условии, что вы будете делать правильные вещи как shared_ptr ref ref count и удалит Foo только один раз, даже если x и y совместно используют один и тот же Foo .Также обратите внимание, что ~Bar
не требуется явной очистки, так как mFoo
будет автоматически удален в деструкторе std::shared_ptr<Foo>
, когда счет Foo станет равным нулю.
class Bar
{
public:
std::shared_ptr<Foo> mFoo;
Bar() :mFoo( new Foo() ) {}
~Bar() { }
};