0

I got some weird problem. I use delete operator inside of class method and I want to know how solve this problem.

This is code:

#include <iostream>

using namespace std;

class A
{
    public:
        int a;

        ~A() {
            cout << "call ~A()" << endl;
        }

        void action()
        {
            /* code here */
            delete this; //this line depends on some if statements
            /* code here */
        }

        void test2() {
            cout << "call test2()" <<  a << endl;
        }

        void test() {
            a = 10;
            cout << "call test()" << endl;

            action();

            //how can I check if data is deleted?
            test2();
        }
};

int main()
{

    A* a = new A();
    a->test();

}

How can I check if data is deleted by delete operator? Is it even possible?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
UnknownError1337
  • 1,222
  • 1
  • 12
  • 16
  • 2
    You are deleting instance of the class within its non-static member function. I think you need to ask yourself "What am I trying to achieve?" – lapk Jul 27 '13 at 11:09
  • For example I got gui, when Button that is child of this Window calls action closeWindow() I need to delete Window, but don't know exactly how, I thought it will be fastest way or use somekind of dispatcher – UnknownError1337 Jul 27 '13 at 11:47
  • You need to destroy actual window, but who said you need to delete instance of C++ class that represents this window? If you are doing Windows message processing, here is [some information](http://stackoverflow.com/questions/8273830/win32-more-object-oriented-window-message-handling-system/8274312#8274312). I suggest you also read comments, Remy Lebeau gives interesting insights on how it is done within Borland VCL. – lapk Jul 27 '13 at 11:59

2 Answers2

5
  1. Using delete this; is nearly always "bad". There are exceptions, but those are really unusual. Think about what you are trying to do. Most of the time, this means that you should have a wrapper object and an inner object that is created/deleted by the wrapper object.

  2. You can't check if something has been deleted (in a reliable way/portable way). In your particular test-case, you are exercising "undefined behaviour" by "using an object after it has been destroyed", which means you can't really tell what is going to happen. You have to trust the C++ runtime that delete does what it says on the label.

Mats Petersson
  • 126,704
  • 14
  • 140
  • 227
3

In C++ there are other return values available than void. Therefore your action can return something that indicates if this has been deleted or not.

Note that you should not access any non-static data members or call any non-static member functions after deleteing this. Some people feel it to be difficult to guarantee so they ban delete this altogether.

Note to opponents that C++ FAQ claims that delete this is legal construct and I haven't also found anything forbidding it.

Öö Tiib
  • 10,809
  • 25
  • 44
  • Practically, avoiding accessing non-static data is enough, but strictly speaking you're probably still invoking UB. Just don't do this. – Lightness Races in Orbit Jul 27 '13 at 11:27
  • 1
    I can not find UB for that case from standard. Can you show where? I am not big fan of such self owning objects. Sometimes such may be reasonable. Then delete this is OK to avoid artificial owners and the `owner->deleteMe(this)` bloat that still ends in same situation: may access nothing nonstatic. – Öö Tiib Jul 27 '13 at 11:36
  • I understand. I thought when action() will return for example even boolean value it will be still wrong way, that's why I create this question, anyway thanks :P – UnknownError1337 Jul 27 '13 at 11:39
  • @ÖöTiib: The standard does not list every case that is undefined. By contrast, cases that are not defined are... undefined. While you're in a member function, it's expected that the owning object exists. Simple as that. There is basically never anything reasonable about `delete this` -- you're messing up ownership semantics. – Lightness Races in Orbit Jul 27 '13 at 11:43
  • @LightnessRacesinOrbit For example some active objects have to be self-owned because they are the root of ownership tree. Making them artificially not root adds concurrency problems for no gain. – Öö Tiib Jul 27 '13 at 11:58