Destructors or Release methods?

Started by
16 comments, last by Aardvajk 10 years, 2 months ago

Every time I design something I fall into this dilemma: should I clear things on destructors or should I make a (public) Release method? And if I make the Release method, should I automatically call it on destructor (again! ohmy.png ) or should I leave the programmer (well... me tongue.png ) free to call it whenever he wants?

Pros and cons that I can miss?

Advertisement

Can you be a little more technical about what you mean by "clear things?" In general, each object should cleanup after itself. If it creates or allocates, it's responsible for releasing or deallocating its own resources. Some objects may need to create/release several times throughout its lifetime, as needed. Leaving those decisions to another object doesn't make sense.

Having a public Release method and also calling it in the destructor sounds like a recipe for disaster.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

I'm also of the idea that an object should clear itself in a transparent way, but in a lot of well known API objects has some kind of public Release method. Why?

EDIT: with "clear things" I mean the usual call of delete commands and pointers nullify

What language are you using?

If you are using C++, look into RAII (http://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization).

If it makes sense to release resources before the objects gets destructed (and its memory freed) then make a public method. If it doesnt then clean it up in the destructor and dont add an unnecessary protected: release() method.

pointer nullify? ....you mean after you delete something you set the pointer to nullptr so if someone calls delete again, it wont crash? Sounds bad. RAII would be more sane. And if you use raw pointers or arrays, make a has_memory_allocated or something member so you know that it can be freed(maybe the allocation has failed in the constructor).


a lot of well known API objects has some kind of public Release method. Why?

Because you don't delete those types of objects. You create them; you release them. Note: if you're talking about COM objects, you can also AddRef/Release in matched pairs.

To clarify, I'm assuming you're talking about an object that, when it's created or allocated, then creates and allocates for itself needed objects. E.g.,


Object::Object()
{
    Create( device ); // EDIT: or device->AddRef()
    GlobalAlloc( myMemory );
}

Object::~Object()
{
    if( device ) Release( device ); // Note: the object's responsibility.
    //device = NULL; // NO!!
    if( myMemory ) GlobalFree( myMemory ); // because this object allocated it.
    myMemory = NULL; // Not really necessary?
}

For COM objects, Release() must be public. How would you release it otherwise? smile.png

Releasing the device (in the above) may not result in the device's destruction, if other objects needed it, called device->AddRef, and haven't called Release yet. That's not this Object's responsibility. The device will take care of itself.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

Well, if I understand correctly - you might want to "release" your memory from time to during the object's lifetime. If you were writing something like a smart pointer, then, sure, a release method that you call is a very sane thing to do, unless you want to duplicate code. Other than a smart pointer, I don't remember if I had to have a clean-up method besides the destructor.


If you were writing something like a smart pointer, ...

I'm not as knowledgeable of smart pointers as I ought to be. However, do you mean shared pointer, perhaps? I was considering heap allocations needed only (exclusive ownership) by the object.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

You can have both, like std::fstream. There there exists a close method, which is called by the destructor if the file is not already closed. You can make it so that calling the clean-up method more than once is safe to do. More often, just releasing and cleaning up in the destructor is the best option. And because you do want to leave the system in a safe state, having clean-up as a method, but not as a destructor is usually bad.

The only times I've seen Release() methods are when there are matching AddRef() or similar, that is reference counted objects.

Edit: There are some more legitimate uses. For example a scripting language may require explicit release methods in order to function correctly/automatically. There are also some reasons to work with interfaces, such as when creating libraries, where it may be cleaner or more desirable to use explicit releasing. In such cases, it's not too uncommon to create RAII wrappers around those interfaces.

This topic is closed to new replies.

Advertisement