开发者

delete this pointer behaviour in g++

开发者 https://www.devze.com 2022-12-16 06:54 出处:网络
#include <stdio.h> class Foo { public: Foo(char x); Foo(char x, int y); ~Foo(); void abc(); void dev();
#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"开发者_StackOverflow中文版 function is still invoked despite being "delete this" is called in function abc before invoking dev ? How does gcc/g++ handles this ?


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.


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.


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.


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.


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.


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.


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.

0

精彩评论

暂无评论...
验证码 换一张
取 消