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:
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
.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
.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":
- 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).- You must be absolutely 100% positive sure that your member
function will be the last member
function invoked on this object.- 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).- 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 delete
ing 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
What Is a Smart Pointer and When Should I Use One
Where Do I Find the Current C or C++ Standard Documents
Difference Between Const Int*, Const Int * Const, and Int Const *
Read Whole Ascii File into C++ Std::String
How to Initialize Private Static Members in C++
Function Pointer to Member Function
When and Why Will a Compiler Initialise Memory to 0Xcd, 0Xdd, etc. on Malloc/Free/New/Delete
What Uses Are There For "Placement New"
Passing a 2D Array to a C++ Function
How to Get the List of Files in a Directory Using C or C++
Accessing Inactive Union Member and Undefined Behavior
Is Segmentation Fault Actual Undefined Behavior When We Refer to a Non-Static Data-Member
Using Arrays or Std::Vectors in C++, What's the Performance Gap
Given an Integer N. What Is the Smallest Integer Greater Than N That Only Has 0 or 1 as Its Digits