Где удалить объект, созданный фабрикой?

Если у меня есть фабрика, которая создает объект и возвращает указатель на него, каким будет лучший способ его удалить:

Вызовом delete в "пользовательском" коде или новой функцией DestructObject, которая должна быть у меня вместе с фабрикой?


person Igor Oks    schedule 11.07.2010    source источник
comment
Зависит от того, кому принадлежит объект после его создания. Но никогда не рекомендуется возвращать указатель, поскольку с ним связана семантика нулевого владения.   -  person Martin York    schedule 11.07.2010


Ответы (4)


В общем случае фабрика может не использовать старый добрый new для размещения объекта. Он может использовать объединение объектов и/или страниц, malloc с размещением new или что-то еще более экзотическое (отображение памяти?). Есть по крайней мере три способа справиться с этим, о которых я могу думать:

  1. Попросите фабрику предоставить метод recycle, который будет вызываться, когда вы закончите работу с объектом.
  2. Возвращает интеллектуальный указатель, который знает, как покончить с объектом, когда не останется ссылок.
  3. Реализуйте собственный оператор delete в самом объекте.

Я не решаюсь рекомендовать один вариант другому, так как за последние пять минут я недостаточно подумал, чтобы высказать окончательное мнение, но я бы предпочел последний вариант в сочетании с обычным интеллектуальным указателем, таким как boost/tr1: :shared_ptr.

person Marcelo Cantos    schedule 11.07.2010
comment
Остерегайтесь передачи объектов через границы DLL с помощью shared_ptr. Тогда используйте intrusive_ptr... Однажды я столкнулся с этой проблемой, и это разрушило мою надежду на то, что при использовании shared_ptr вы всегда в безопасности. - person jdehaan; 11.07.2010
comment
@jdehaan: shared_ptr вызовет пользовательский delete, который всегда находится в безопасности. - person Marcelo Cantos; 11.07.2010
comment
@Marcelo, спасибо за эту точность, возможно, случай, который у меня был, вероятно, был связан со старой версией boost::shared_ptr под Windows с подключаемыми dll, которые часто загружались / выгружались. Я переключился на разработку .NET пару лет назад. Обоснование повышения в отношении intrusive_ptr стало немного неясным: boost. org/doc/libs/1_43_0/libs/smart_ptr/intrusive_ptr.html. Не уверен, что тогда есть веские причины предпочесть intrusive_ptr! - person jdehaan; 11.07.2010
comment
@jdehaan: проблема могла быть связана с использованием оператора delete по умолчанию, который будет вызывать любой базовый распределитель памяти, связанный с вызывающим кодом. Если аллокатор связан статически с любой стороны (или просто два разных аллокатора связаны динамически), то неприятные сбои не за горами. Также обратите внимание, что пользовательский delete, о котором я говорю, должен быть скомпилирован в библиотеку, поэтому его нельзя объявлять inline. - person Marcelo Cantos; 12.07.2010
comment
@Марсело, вот и все! Без значения по умолчанию delete код работает хорошо... Большое спасибо за пояснение. - person jdehaan; 12.07.2010


Следующий код дает возможность не думать о том, кто должен удалить только что созданный объект.

class FooFactory
{
public:
    static std::auto_ptr<Foo> CreateInstance();
};

// transmit ownership of created object from factory to 'a' variable
std::auto_ptr<Foo> a = FooFactory::CreateInstance();
// using the created object is not required
FooFactory::CreateInstance();
person Sergey    schedule 11.07.2010

Наиболее универсальным решением этой проблемы является получение вашего класса от базового класса, который имеет виртуальную «убийственную» функцию. Что-то вроде этого:

class IDisposable {
public:
    virtual void Release() = 0;
};

Обычно считается, что полиморфные объекты должны иметь виртуальные деструкторы для поддержки правильной очистки объекта. Однако это неполно, поскольку не учитывает потенциально различное управление памятью объектов.

С другой стороны, этот метод не требует использования виртуальных деструкторов. Теперь она заменена функцией Release, которая делает и то, и другое: вызов правильного деструктора и освобождение памяти соответствующими средствами.

заботится об уничтожении объекта

оба: уничтожить

Объект, возвращенный с фабрики, будет реализовывать этот «интерфейс».

person valdo    schedule 11.07.2010