views:

197

answers:

7
#include <stdio.h>

class Foo {

        public:
                Foo(char x);
                Foo(char x, int y);
                ~Foo();
                void abc();
                void dev();
};

void Foo::dev()
{

        printf("inside dev \n");
}

void Foo::abc()
{

        printf("inside abc \n");
        delete this;
        dev();
}

Foo::Foo(char x)
{

      printf("inside 1 argu const---------------");

}

Foo::~Foo()
{

    printf("inside 1 argu dest---------------");
}

#include "test.h"

int main()
{

        Foo *obj=new Foo('a');
        printf("%u inside main\n", obj);
        obj->abc();
        return 0;
}

After looking at the output of the program, it seems that "dev" function is still invoked despite being "delete this" is called in function abc before invoking dev ? How does gcc/g++ handles this ?

+11  A: 

The object might be still available for undefined time. Also, delete doesn't affect the pointer in question.

Delete just calls the destructor on the object instance. Delete returns the memory to the pool but it is undefined (and runtime related) as to when this memory will be reused (if at all). The object can very well be available for the rest of the duration of the program but the point is: don't count on it.

There is a not so obvious pitfall to take notice of: the object has no way of knowing if it was allocated dynamically. Hence, if the object was statically allocated calling, delete this on the said object will prove problematic. This isn't the case above though.

jldupont
Calling a non-static member function after after deleting the object is NOT legal. In this case you'll most likely get away with it, since the function isn't virtual and doesn't access any members. But the behaviour is undefined so, just like in real life, never try to do anything with a zombie.
Mike Seymour
@Mike: agreed. When presented with this sort of design, I would refactor to have an "agent" take care of tracking the object's lifecycle. Of course, there are many ways to go about this.
jldupont
A: 

All delete does is call the destructor, then operator delete (the built-in version, if there's no override in your class). It's not any smarter than free(), really. There's nothing to prevent you from using a deleted object. It won't work right, sure.

Calling delete this; is pretty risky as well. The object won't be valid from that point on, and if you try to call methods or access members, you're in undefined-operation territory.

Mike DeSimone
+6  A: 

Delete just deallocates the memory (calling the destructor as well). Basically you called dev with a trash this pointer, it works only because dev wasn't virtual and it doesn't try to access any member variables, otherwise it would likely access violate just like using any other invalid pointer.

Ruddy
+1  A: 

I would expect dev(); to be called at this point but it's undefined behaviour as the this pointer is pointing at an object that has been destroyed. The reason that your call appears to be succeeding is because because you're getting lucky and nothing else has claimed the memory pointed to by this when you are calling dev(), otherwise the results would be "interesting", to say the least.

Timo Geusch
+1  A: 

delete this will not normally affect the this pointer itself, so it can still be used to call the function. This behaviour is undefined though - it might work, it might not. In general, delete this is a bad idea in C++. The only justification for using it is in some reference counted classes, and there are beter approaches to reference counting which do not require its use.

anon
+2  A: 

How does gcc/g++ handles this ?

It handles it as you can see from your testing.

It's risky though: for example if you modified the dev method to access any instance member data of the Foo class, then your behaviour (i.e. calling the dev method after the Foo instance has been deleted) would be illegal, and the behaviour would be undefined: the actual behaviour would vary depending on what was happening elsewhere in the program, for example on whether the memory which the Foo instance occupied (and which was released when the Foo instance was deleted) has been reallocated by another thread.

The behaviour would also be different if the dev method were a virtual method, and Foo were a base class or a subclass in an inheritance hiearchy.

It would be better if you defined dev as a static method:

class Foo {

public:
    Foo(char x);
    Foo(char x, int y);
    ~Foo();
    void abc();
    static void dev();
};

If you call a function which cannot be defined as static (because it's virtual or because it accesses instance member data), then it would be illegal to do what you were doing.

ChrisW
+1  A: 

Delete doesn't delete the code or static variables of a class, just the instance variables. As other people pointed out, the behavior you get using an object pointer after you delete it is undefined, however.

But ask yourself this (or maybe ask stackoverflow ;-): Can you call a static member function of a class if no instances of the class exist? (The answer is yes, of course.)

If dev() were static, this code would be perfectly legal.

Richard Pennington
I'm not so sure it would be legal. dev() is just shorthand for this->dev(), which uses the deleted this pointer. Foo::dev() would be legal, however.
KeithB
dev() is a call to the function dev(). If dev() is static, there is no this pointer involved in the call.
Richard Pennington