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?
freeshould not be used with actual C++ objects.freeshould be used withmalloc, so you shouldn’t be usingfreeon something you allocated withnew.As to why you can
deleteconst objects, that’s simple:Now what? If you couldn’t delete that, then you’d have to do this:
Having an object be
constmeans 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 deleteto take a pointer to const (which is different from a const pointer):What is the first line of this function going to be? The purpose of
operator deleteis to free memory that was allocated byoperator 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: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 byp(or modifying memory based on that address), it would be silly of the specification to then allow you to defineoperator deletethis 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?