views:

169

answers:

4

If I have a factory, that creates an object and returns a pointer to it, what will be a better way to delete it:

By delete call in the "user" code, or by a new DestructObject function which I should have together with the factory?

+8  A: 

In the general case, the factory might not use plain old new to allocate the object. It may use object and/or page pooling, malloc with placement new, or something even more exotic (memory mapping?). There are at least three ways to handle this that I can think of:

  1. Have the factory supply a recycle method to be called when you are done with the object.
  2. Return a smart pointer that knows how to do away with the object once no referers remain.
  3. Implement a custom delete operator in the object itself.

I hesitate to recommend one over the other, since I haven't given it enough thought in the last five minutes to proffer a definitive opinion, but I would tend to favour the last option in combination with a regular smart pointer like boost/tr1::shared_ptr.

Marcelo Cantos
Beware passing around objects over DLL boundaries with shared_ptr. Use an intrusive_ptr then... I came over that issue once and that destroyed my hope that when using shared_ptr, then you are always on the safe side.
jdehaan
@jdehaan: The shared_ptr will invoke the custom `delete` which is always on the "safe side".
Marcelo Cantos
+1 for boost::shared_ptr. That is the best way to go.
Michael Aaron Safyan
@Marcelo, thanks for that precision, maybe the case I had was probably related to an old version of boost::shared_ptr under Windows with plug-in dlls that were loaded/unloaded frequently. I switched to .NET development a couple of years ago. The boost rationale regarding intrusive_ptr has become really a bit unclear: http://www.boost.org/doc/libs/1_43_0/libs/smart_ptr/intrusive_ptr.html. Not sure what are good reasons to prefer intrusive_ptr then!
jdehaan
@jdehaan: The issue may have been related to use of the default `delete` operator, which will invoke whatever underlying memory allocator is linked into the calling code. If the allocator is linked statically on either side (or simply two different allocators linked dynamically), then nasty crashes are just around the corner. Also note that the custom `delete` I'm referring to *must* be compiled into the library, so it mustn't be declared `inline`.
Marcelo Cantos
@Marcelo, That's it! Without the default `delete` the code works well... Thank you so much for clarifying this.
jdehaan
+1  A: 

The best way to delete it manually would be not at all.

BlueRaja - Danny Pflughoeft
Sarcasm does not translate well to any recorded format. It would be best advices to avoid it and be specific rather than hiding the meaning in links. But +1 for smart pointers as a possible method.
Martin York
A: 

The most versatile solution for this problem is to derive your class from a base class that has a virtual "killing" function. Something like this:

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

It's generally believed that polymorphic objects should have virtual destructors to support proper object cleanup. However this is incomplete, because it doesn't account for potentially different memory management of objects.

On the other hand this method doesn't require to use virtual destructors. It's now replaced by Release function that does both: invokation of the correct destructor and releasing the memory by the appropriate means.

takes care of the object destr

both: destruct

The object returned from the factory will implement this "interface".

valdo
+1  A: 

The following code provides an opportunity not to think about who should remove the newly created object.

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();
Sergey