What is happening during `delete this;` statement?

前端 未结 7 2859
余生分开走
余生分开走 2021-02-20 08:47

Please consider the following code:

class foo
{
public:
    foo(){}
    ~foo(){}
    void done() { delete this;}
private:
    int x;
};

What is

相关标签:
7条回答
  • 2021-02-20 09:04

    In both cases your heap will get corrupted. Of course, you can't use in option 2 "->" if the left value (in this case, "a") is not a pointer, the correct form in option 2 would be a.done(); But yeah, you should get a heap corruption if you try to delete 1) what's been already deleted, or 2) local variable.

    Calling "delete this" is technically valid and frees the memory.

    EDIT I was curious and actually tried this:

    class foo 
    {
    public: 
        foo(){} 
        ~foo(){} 
        void done() { delete this; } 
        void test() { x = 2; }
        int getx() { return x; }
    private: 
        int x; 
    } ;
    
    
    int main(int argc, char* argv[])
    {
        foo *a = new foo();
        a->done();
        a->test();
        int x = a->getx();
        printf("%i\n", x);
        return x;
    }
    

    A call to printf will succeed, and x will hold the value 2.

    0 讨论(0)
  • 2021-02-20 09:06

    This question has been answered but I will add a new point that if your class does call delete this then you should also make the destructor private.

    This ensures that only the class can delete itself.

    If you make your destructor private above, both of your code samples will fail to compile.

    0 讨论(0)
  • 2021-02-20 09:11

    Both would cause an error.

    The first pointer is deleted twice, with the second delete causing the error whereas the second one is allocated on the stack and cannot be implicitly deleted (error caused by first invocation of destructor).

    0 讨论(0)
  • 2021-02-20 09:16

    Both would cause an error, what you want is:

    void main()
    {
       foo* a = new foo();
       a->done();
    }
    

    Which the compiler will expand to something like below, which I hope makes deleting "this" a bit less confusing.

    void __foo_done(foo* this)
    {
       delete this;
    }
    
    void main()
    {
       foo* a = new foo();
       __foo_done(a);
    }
    

    See also, Is it legal (and moral) for a member function to say delete this?

    0 讨论(0)
  • 2021-02-20 09:17

    I would be very cautious about the context in which you free memory. Whilst calling "delete this;" will attempt to free the memory associated with the class structure, that operation has no means of deducing the context of the original memory allocation, ie, if it's allocated from the heap or the stack. My advise would be to rework your code so that the deallocation operation is invoked from an external context. Note that this is different from deallocating structures internal to the class, in that case, use the destructor.

    0 讨论(0)
  • 2021-02-20 09:25

    delete this; is allowed, it deletes the object.

    Both your code snippets have undefined behavior - in the first case deleting an object that has already been deleted, and in the second case deleting an object with automatic storage duration.

    Since behavior is undefined, the standard doesn't say whether they will cause an exception or heap corruption. For different implementations it could be either, neither, or both, and it may or may not be the same each time you run the code.

    0 讨论(0)
提交回复
热议问题