Delete memory from inside a class

Started by
14 comments, last by RabblePants 14 years, 3 months ago
MyClass* a = new MyClass;

...

delete a;
a = 0;
The code above would allocate memory for my object 'a', and later bring it back. Say this instead:
class MyClass {
private:

    ...

public:

    MyClass() {
        ...
    }

    ~MyClass() {
        ...
    }

    void destroy() {
        delete this;
    }
};
And now:
MyClass* a = new MyClass;

...

a -> destroy();
Would the memory allocated for 'a' now be released?
Advertisement
Here.
I tried it and the data (I just put an int in) was 0xfeeefeee (implying its been deleted (well with visual studio)).

Its a really "bad" thing to do though, why would you do this instead of just using delete? Is this just out of curiosity or were you actually planning on using it?

Interested in Fractals? Check out my App, Fractal Scout, free on the Google Play store.

While it's legal, this is very bad mojo :) It goes against my "if you do, you must undo" guideline (even though there's discussion on the topic).

(a) The object did not allocate its own memory (something else did, and then called its constructor), and so should not be responsible for deallocating it.

(b) As a C++ programmer if I see a "new" somewhere I expect to see an accompanying "delete" as well. I certainly don't expect to call "destroy" on an object if I "new"'d it somewhere else.

(the above is in addendum to the usual risks and cautionary words as they apply to suicidal classes, not a replacement)

So yeah - it will work, the memory will be deallocated as you expect, and is perfectly legal .. but it's bad mojo =)
All objects created with this "self destructive" behaviour are added to a manager. So you can say that you give all the resposibility to the manager when its created. It is the base object of my gui that uses this destroy method in order to remove ALL the children that is attached to it. So codewise it looks something like this:

gui::Window* window = new Window;window -> setSize(400, 300);window -> setPosition(100.0, 300.0);...manager.add(window);...// Main loop.while (1) {    ...manager.update();}


So say that you hit the close button on the window object and have to do something like this:

while (1) {    if (window -> closeButtonIsClicked()) {    delete window;}...}


Instead the manager has a list with all the frames and when the close button is clicked it gets a message that it should DESTROY the frame. When it does it just calls the window's destroy method and removes it from the list.
It's actually useful for a certain kind of intrusive reference counting implementation.
It sounds like your putting a lot of effort to get around behavior C++ already has built in aka the destructor.

You could replace the pointers with smart (strong and weak) pointers, which provides a much safer basis for deleting the allocated memory automatically. You just need to put all of your destruction code into the destructor.

Like what you said in your example, you want the object's children to be deleted as well. Your class can store strong pointers to the children (ensuring their lifespan till the parents deletion) and the children have weak pointers to the parent (ensuring the children don't accidently keep a parent alive).

With the reference counting provided by the smart pointer, your resource manager can see if anything other than itself has a strong pointer to the class. If it they don't and you want to destroy the object, all you have to do is basically pop it out of the resource manager. When no more objects have a copy of the smart pointer, all of the destructor code gets calls. In the destructor is where you can have the class perform the destruction of the children.

[edit]
You can even still create a seperate function from the destructor that performs all of the cleanup, without actually calling delete this. This would allow you to call it whenever you want, plus not duplicate code if you just want the destuctor to do it too (by adding a call to it in the destructor).

"I can't believe I'm defending logic to a turing machine." - Kent Woolworth [Other Space]

Quote:Original post by rikardo
Instead the manager has a list with all the frames and when the close button is clicked it gets a message that it should DESTROY the frame. When it does it just calls the window's destroy method and removes it from the list.


Well, let me ask you this - what would you gain from calling "obj->destroy()" instead of "delete obj" and still provide the same functionality?

Putting it differently: if I got a hold of your code and removed the "destroy()" function completely and replaced all references to that function with "delete ptr;" .. what would be lost/broken in the process?
Understand your view, but the object which invokes the destroy method looks somthing like this:

void destroy() {    for all children {        currentChildren -> destroy();    }    delete this;}


If you remove this code it will not destroy all the children. And if you try to put this code in the destructor then a delete this call will produce a infinite loop, since after the delete call, the destructor is called.
So, replace it like so:
Whatever::~Whatever(){   for(Child *child in children)   {      delete child;   }}

The caller uses delete instance; instead of instance->destroy()

And hey presto! Its idiomatic and works perfectly. Now, add smart pointers to the above and you save yourself a host of headaches.

This topic is closed to new replies.

Advertisement