Is "Delete This" Allowed in C++

Is delete this allowed in C++?

The C++ FAQ Lite has a entry specifically for this

  • https://isocpp.org/wiki/faq/freestore-mgmt#delete-this

I think this quote sums it up nicely

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

Is it safe to `delete this`? [duplicate]

delete this is legal and does what you would expect: it calls your class's destructor and free the underlying memory. After delete this returns, your this pointer value does not change, so it is now a dangling pointer that should not be dereferenced. That includes implicit dereferencing using the class's member variables.

It is usually found in reference-counted classes that, when the ref-count is decremented to 0, the DecrementRefCount()/Release()/whatever member function calls delete this.

delete this is typically considered very bad form for many reasons. It is easy to accidentally access member variables after delete this. Caller code might not realize your object has self-destructed.

Also, delete this is a "code smell" that your code might not have a symmetric strategy for object ownership (who allocates and who deletes). An object could not have allocated itself with new, so calling delete this means that class A is allocating an object, but class B is later freeing it[self].

Is delete allowed to modify its parameter?

Before the deletion, ptr's value was valid. After the deletion, the value was invalid. Therefore the value changed. Valid values and invalid values are mutually exclusive -- a value cannot be simultaneously valid and invalid.

Your question has a basic misconception; you're conflating these two different concepts:

  • The value of a variable
  • The representation of a variable in memory.

There isn't a one-to-one correspondence between these two things. The same value may have multiple representations, and the same representation may correspond to different values.


I think the gist of your question is: can delete ptr; change the representation of ptr?. To which the answer is "Yes". You could memcpy the deleted pointer into a char array, inspect the bytes, and find them all to be zero-valued bytes (or anything else). This is covered in the standard by C++14 [basic.stc.dynamic.deallocation]/4 (or C++17 [basic.stc]/4):

Any other use of an invalid pointer value has implementation-defined behavior.

It's implementation-defined and the implementation could define that inspecting the bytes gives bytes with value zero.


Your code snippet relies on implementation-defined behaviour. "Valid code" isn't terminology used by the Standard, but the code might not remove the intended item from the hash table.

As alluded to by Stroustrup, this is an intentional design decision. An example usage would be a compiler in debug mode setting deleted pointers to a particular representation, so that it can raise a runtime error if a deleted pointer is subsequently used. Here's an example of that principle in action for uninitialized pointers.

Historical note: In C++11 this case was undefined, rather than implementation-defined. So the behaviour of using a deleted pointer was identical to the behaviour of using an uninitialized pointer. In the C language, freeing memory is defined as putting all pointers to that memory into the same state as an uninitialized pointer has.

What's the equivalent of new/delete of C++ in C?

There's no new/delete expression in C.

The closest equivalent are the malloc and free functions, if you ignore the constructors/destructors and type safety.

#include <stdlib.h>

int* p = malloc(sizeof(*p)); // int* p = new int;
...
free(p); // delete p;

int* a = malloc(12*sizeof(*a)); // int* a = new int[12];
...
free(a); // delete[] a;

How can I know if I need to delete something in C++?

There are a couple different patterns that apply:

  1. The always-allocate pattern. In this approach, the class doesn't take ownership of the passed-in resource, rather it makes a copy in a buffer it allocated and therefore knows how to deallocate in its destructor. The original parameter is owned by the code calling the class, and that caller should clean up its own data whenever it wants, because the class instance has an independent copy. Example: std::string.

  2. The caller-specified-deleter pattern. In this approach, the class does take ownership, and to accomodate a variety of allocator/deallocator pairs, it accepts a parameter which is a function or function object that knows how to deallocate the data. The class destructor will call this deleter function/function object, performing the correct deallocation (or none at all) needed for that particular buffer. Example: std::shared_ptr.

  3. The nested-ownership pattern. Here, the class just keeps a pointer or reference to the original block of data. The caller still has ownership and the responsibility to free the data, but it additionally is required to keep that block valid for as long as the class instance it created exists. This is the lowest overhead at runtime, but also the most difficult to keep track of. Example: by-reference variable capture in a C++11 lambda.

Whichever of these you use for your class design, make sure you document it so the users of your class aren't left wondering.

Is is safe to `delete this` in a virtual member function?

Yes, so long as you don't use this afterwards, and neither does anyone else with a pointer to *this, and this was guaranteed to be allocated by new as exactly the type you are deleting it as, or possessing a virtual destructor. (ie, never as a member of another object, in a std::vector, as an automatic storage variable, as a static variable, as a temporary, not new[], not placement new, etc etc etc)

This includes calling non-virtual methods, virtual methods, member access, calling dtors, and a myriad of other things; almost anything other than return; on the next line and somehow every other pointer to *this being cleaned up before you delete this; (or deterministically never being used).

As a general rule, the level of control you have to have over your objects lifetime is so great to make delete this; safe that you can refactor the lifetime management to be external to the class and in a smart resource owner, which maybe maintains its state as a pImpl which it deletes. c++ adores value types, and a type that delete this; can never be treated as a value.

There is nothing in the standard that makes delete this; extra dangerous for virtual objects, other than the higher tendency to inherit.

All types that delete this; should have either a virtual destructor or be final to avoid inheritance issues.

Is delete this a bad idea? [duplicate]

The FAQlite answers this quite well:

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

Here's how I define "careful":

  1. You must be absolutely 100% positive 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).
  2. You must be absolutely 100% positive sure that your member
    function will be the last member
    function invoked on this object.
  3. You must be absolutely 100% positive 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).
  4. You must be absolutely 100% positive sure that no one even touches
    the this pointer itself after the
    delete this line. In other words, you
    must not examine it, compare it with
    another pointer, compare it with NULL,
    print it, cast it, do anything with
    it.

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.

Basically, you need to take the same care as you do with deleteing any other pointer. However, there are more areas where things can go wrong with a member function committing suicide, compared with an explicitly-declared pointer.



Related Topics



Leave a reply



Submit