I've just noticed that the pointers passed to delete
can be const
qualified while those passed to free
cannot. That is really a surprise to me.
And in C++ an overload to operator delete
should have a signature like:
void operator delete(void* p);
But adding a const
to the parameter pointer is invalid:
void operator delete(void const* p);
May anyone tell me why delete
is designed this way?
It is illegal to delete a variable that is not a pointer. It is also illegal to delete a pointer to a constant.
It destroys the memory at the runtime. It should only be used either for the pointers pointing to the memory allocated using the new operator or for a NULL pointer. It should only be used either for the pointers pointing to the memory allocated using malloc() or for a NULL pointer.
The address of the pointer does not change after you perform delete on it. The space allocated to the pointer variable itself remains in place until your program releases it (which it might never do, e.g. when the pointer is in the static storage area).
You cannot free const char * because it is const . Store pointers received from malloc in non-const pointer variables, so that you can pass them to free . You can pass char * arguments to functions taking const char * arguments but opposite is not always true.
free
should not be used with actual C++ objects. free
should be used with malloc
, so you shouldn't be using free
on something you allocated with new
.
As to why you can delete
const objects, that's simple:
const Type *ptr = new Type(...);
Now what? If you couldn't delete that, then you'd have to do this:
delete const_cast<Type*>(ptr);
Having an object be const
means that it cannot be modified. You cannot cause the object to go from one state to another state. Deletion is throwing it away. Meaning that it no longer exists in any state, whether the original one or some other modified form. Deletion is an operation that exists outside of the object's mutability state, much like construction.
Conceptually, deletion is neither const nor non-const. While a destructor is a non-const function, the idea of destructing an object is simply outside the domain of const or non-const.
OK, let's say you define operator delete
to take a pointer to const (which is different from a const pointer):
void operator delete(void const* p);
What is the first line of this function going to be? The purpose of operator delete
is to free memory that was allocated by operator new
. That will require poking at bits on the memory allocation heap. And to do that, you need a pointer that does not point to const data:
void *ptr = const_cast<void*>(p);
Welcome to undefined behavior. While C++ allows you to do this, the specification is very clear that the results of attempting to write to ptr
(or any address based on it) are undefined. You were given a const pointer; you were told by the outside world not to modify the stuff it pointed to. C++ provides no guarantees about what happens when you break that contract.
Since the specification states that this is undefined behavior, and since operator delete
(in most cases) cannot do its job without modifying the memory pointed to by p
(or modifying memory based on that address), it would be silly of the specification to then allow you to define operator delete
this way. It would basically be canonizing the idea of shooting yourself in the foot.
Yes, in virtually every case, this would be completely safe. But since you're going to cast away the const anyway, why even bother to allow the rather dubious idea in the first place?
free
is C function. Its signature is 20-30 years old, from times where there were no const
in C language (and there was no C++ language as well). C++ compiler treats free
like every other function, and can't let it accept const
pointer without cast, because free
could possibly change object pointed. Actually, it does, as well as delete
, but C++ doesn't know that free
is used for memory management.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With