13

Possible Duplicate:
C++: Delete this?

In C++, is it ok to delete the self object in function definition. What are side effects of this?

class MyClass {

public:
    void ~myClass() {}
    void myFunction() { 
        // logic here
        delete this;
    }
}

Thanks!

Community
  • 1
  • 1
venkysmarty
  • 11,099
  • 25
  • 101
  • 184
  • 3
    http://stackoverflow.com/questions/3150942/c-delete-this. Constructors and destructors don't have return type. Not even **void**. – Mahesh Aug 05 '11 at 06:04
  • 1
    What you have there won't even compile? Did you try it out at your end? – Shamim Hafiz - MSFT Aug 05 '11 at 06:05
  • The only time I've ever done this is when writing plugin architecture, where the delete needed to happen in the loaded objects memory space. The destructor was private and pure virtual, and classes inherited from it. – GManNickG Aug 05 '11 at 06:13

5 Answers5

19

From parashift FAQ:

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

As long as you're careful, it's OK for an object to commit suicide (delete this).

Here's how I define "careful":

  • You must be absolutely 100% positively sure that this object was allocated via new (not by new[], nor by placement new, nor a local object on the stack, nor a global, nor a member of another object; but by plain ordinary new).

  • You must be absolutely 100% positively sure that your member function will be the last member function invoked on this object.

  • You must be absolutely 100% positively sure that the rest of your member function (after the delete this line) doesn't touch any piece of this object (including calling any other member functions or touching any data members).

Naturally the usual caveats apply in cases where your this pointer is a pointer to a base class when you don't have a virtual destructor.

Nawaz
  • 353,942
  • 115
  • 666
  • 851
  • 3
    You were doing so well... but the end is wrong. You can do anything you want with the `this` pointer that doesn't involve dereferencing it. Specifically, all your examples "compare with another pointer, compare with NULL, print it" and so on are actually quite safe. – Ben Voigt Aug 05 '11 at 06:09
  • 1
    Legal yes. Moral: No. Consider the separation of concerns. You are adding resource management logic into business object. – Martin York Aug 05 '11 at 06:11
  • 2
    The first three bullets are absolutely correct, Nawaz :) – paulsm4 Aug 05 '11 at 06:14
  • @Martin You make a good point, but sometimes this is the only viable option. Say you're writing a shared library that exports a C++ class via an abstract interface. Then the deletion of this object **must** happen within the memory space of the library. So `delete this` is the only safe option. – Praetorian Aug 05 '11 at 06:20
  • @Praetorian: Having to delete memory within the same library is no longer true. This was the result of the MS statically linking the C-runtime with each library. The resulted in a different heap for each library and thus dynamically allocated objects had to be deallocated by the same library so they were placed back on the correct heap. With the advent of dll and MS changing the default in visual studio to link the C-runtime dynamically this is no longer true (unless for some strange reason you still link the C-runtime statically). – Martin York Aug 05 '11 at 06:52
  • @Praetorian: But this ha nothing to do with my original point. Which is a design issue (rather than a coding one). – Martin York Aug 05 '11 at 06:54
  • @Martin: Sorry, but what you describe is incredibly fragile. COM requires that deallocation be done within the same library for a very good reason: The calling code might be compiled with a different compiler, or even written in a different language. Even when the DLL version of the runtime is used, there are frequently many different (and incompatible) runtimes in the same process. – Ben Voigt Aug 05 '11 at 13:54
  • @Ben: I believe that is a common fallacy in modern applications (COM was written when C-runtime was statically linked). But I would love to have a real question on the subject so that people that know what they are talking about (ie **not me**). The point is that nowadays a "with a single run-time" this hocks-pockus is not required. – Martin York Aug 05 '11 at 14:56
  • @Martin: Consider: an application with components built in VB6, VC++ 2005, and VC++ 2010. Where's the "single run-time"? That combination is fully supported by COM. If you're in the business of selling reusable components in binary form, you don't tell your users they have to use the same compiler version you did so they can share a run-time. (Mostly because their other component vendor, the one who makes the widget they absolutely can't live without, has decreed a different compiler.) Anyway, the only common fallacy is the idea that any complex app can have a single shared CRT. – Ben Voigt Aug 05 '11 at 15:04
  • @Ben: Yes in this slightly weird edge case (I consider it weird as I don't use binary components built on old/old/old/old systems). Here you will need to assume that there is more than one run-time. But that does not change my original statement. If you have a single runtime (which to me has never been a problem for more than a decade) this is a fallacy. But as I said please open up as a question get the community to respond. I am a single developer with only limited experience. – Martin York Aug 05 '11 at 15:31
  • @Martin: It's neither weird, nor an edge case. It could be the latest version of Visual C++, the latest version of mingw gcc, and the latest version of Delphi. Or it could be VS2010 and VS.next, three months after VS.next releases. You'd hardly call VS2010 "old old old" at that point. – Ben Voigt Aug 05 '11 at 17:20
  • @Ben Voigt: In my limited experience. This is an edge case. I find it unlikely that the situation would occur. – Martin York Aug 05 '11 at 17:41
13

You may delete an object from within itself, but it is necessary that you do not, afterward, access any member variables or functions of that class instance after doing so.

Zoey
  • 2,391
  • 2
  • 22
  • 28
  • -1 Wrong. You can call functions as long as they are not virtual and don't access members. – Luchian Grigore Aug 05 '11 at 06:08
  • 4
    @Luchian: +1 to counter. You're wrong, here. What you're doing is trying to describe undefined behavior, which is, of course, silly. Sure on most platforms that's fine, but that no longer has anything to do with C++, but C++ on a platform with a certain compiler with certain weather, etc... – GManNickG Aug 05 '11 at 06:11
  • "delete this" is a common idiom in Microsoft-lane (i.e. for COM/ActiveX objects). But it can ONLY be used for objects created with new (like COM/ActiveX objects). And you absolutely need to make sure it's the LAST thing the object does. – paulsm4 Aug 05 '11 at 06:13
  • 6
    @Luchian, what, pray tell, will those member functions do (in implementation of themselves) if not dereference `this`? Seems a bit silly to have a non-static member function that doesn't do something with member variables, doesn't it? – dash-tom-bang Aug 05 '11 at 06:13
  • 1
    On all compilers I've worked with a call to a non-virtual method results in {call A::foo} after placing arguments on the stack. And I'm 99% sure calling methods like this works every time. – Luchian Grigore Aug 05 '11 at 06:14
  • 1
    @dash-tom-bang Just because it's silly doesn't mean it's not valid. I'm not saying I do it, I'm saying it CAN be done. – Luchian Grigore Aug 05 '11 at 06:15
  • 4
    @Luchian: Like I just said, it's undefined behavior in C++. How it happens to work on your computer under a certain compiler has nothing to do with the C++ *language*. – GManNickG Aug 05 '11 at 06:15
  • @Luchian Grigore You're missing the point. A member function that is non-virtual and doesn't access member variables should be static. Then you can invoke the function all you want, since such invocation does not require the class instance. – Praetorian Aug 05 '11 at 06:16
  • @GMan can you provide some references? – Luchian Grigore Aug 05 '11 at 06:17
  • @Praetorian Not missing the point, I perfectly understand what you're saying. You need to understand that it CAN be done (I'm not saying it SHOULD be done). – Luchian Grigore Aug 05 '11 at 06:18
  • class A { void foo(){printf("hello"); } int main(){ A* a = NULL; a->foo(); } will work. – Luchian Grigore Aug 05 '11 at 06:22
  • @Luchian Grigore You keep saying it *can* be done; and maybe it can be on your compiler. But every non-static member function has the `this` pointer passed to it implicitly, and AFAIK there's nothing in the standard that says a compiler cannot generate code to dereference `this` within the function, just for kicks. So saying it works in one particular case is nowhere near the same as saying it is a legal thing to do as far as C++ is concerned. – Praetorian Aug 05 '11 at 06:24
  • 1
    @Luchian: Read §3.8/1-5. In fact, one of the examples shows undefined behavior for calling a member function on an object who's lifetime has ended. – GManNickG Aug 05 '11 at 06:28
  • 2
    @luchian: Define "work". For me, "works" means "does what I expect with well-defined behavior". You have undefined behavior at `a->foo()`; [I've written an entire Q&A on it](http://stackoverflow.com/questions/2474018/when-does-invoking-a-member-function-on-a-null-instance-result-in-undefined-behav). If you don't *care* about undefined behavior, that's fine, but then you've already lost the argument (and quality of code!). – GManNickG Aug 05 '11 at 06:30
  • 1
    @lucian: The prominent point here is not if it works (under some definition of "works"). One should not rely on undefined behaviour even if every implementation honors that. Tomorrow we may find a way to do something better by stop honoring that non-standard behaviour; what then? should we stop improving things or start to broke your code? Often in the past happened that private/nonstandard behaviours was preseverd against optimizations because of existing codebase. You should simply not rely on that (nor advise someone to do it). In a nutshell: be polite! – FxIII Jan 15 '14 at 09:31
2

It's pretty dangerous. Consider this:

void foo() {
   MyClass bar;
   bar.myFunction(); // calls delete
}  // bar goes out of scope, calls delete again

Check out this C++FAQ 16.15 entry for when doing delete this is possible - it's legal, just needs to be used bery carefully.

Mat
  • 202,337
  • 40
  • 393
  • 406
2

The side effects of that are that the object is no longer valid, nor are pointers or references to that object.

I've seen this pattern a lot of places. Typically it's used in a reference counting sort of situation, when the last reference to the object goes away the object deletes itself. It's also typically paired with a factory function of some sort, e.g. a static class member function named Create, taking no parameters, and returning a pointer to the class. The body of this function does the corresponding new, and your constructor can even be private (that way people don't create the object in a way that will mess up your cleanup code).

dash-tom-bang
  • 17,383
  • 5
  • 46
  • 62
0

Depends on your definition of ok!

You can do this, if you are careful, but you shouldn't do it without very good reason, because no-one will be expecting it, and because there is no guarantee that the object has been allocated with new.

Nikki Locke
  • 2,759
  • 6
  • 29
  • 53