Why is the delete operator required to be static?
I found this one question asking the same thing, however only the 'new' part was answered, so here goes again.
Why is the delete operator required to be static? Somehow it doesn't make sense. The new operator makes perfect sense, just like the constructor can't be virtual, neither can the new operator. However, the destructor can (and should) be virtual when you use inheritance, in order to allow destruction of objects being used (by way of polymorphism) as a base class.
I understand that, when the delete operator is called, the object has already been destroyed, so no 'this' exists. Yet it still makes sense, using the same reasoning as with virtual destructor, to have the delete operator match the new operator which created the object.
This is what I mean
class A
{
public:
virtual ~A() {}
};
class B : public A
{
public:
void* operator new (size_t sz);
void operator delete (void* ptr, size_t sz);
};
now if we do
A *ptr = new B();
delete ptr; // <-- fail
A's delete operator (default) should've been called, since it's static an开发者_开发百科d it's not known (for anything but the trivial case here) at compile time which delete-operator is the correct one.
However, I made a small test program with the code above (just malloc/free in the new/delete operators, and print statement in delete), and compiled it using g++. Running it quite unexpectedly produced the output in B's delete operator.
My (real) question is this: Is there some implicit 'virtualness' to the delete operator? Is it only static in the no-this-pointer sense? Or is this just a g++ feature?
I started looking through the C++ specification, but I must admit, I was bit overwhelmed by it, so any help appreciated.
The answer in the language rules is really in 12.5 [class.free].
If you are deleting via a pointer to a base class then the destructor must be virtual or you get undefined behaviour. Otherwise, the implementation has to determine the dynamic type of the object being deleted.
12.5/4 says that when the delete
isn't prefixed by ::
then the deallocation function is determined by looking up delete
in the context of the dynamic type's virtual destructor. This ensures virtual-like lookup, even though operator delete
is always a static
member function.
Raw allocation and deallocation happen conceptually outside of the object's lifetime so by the time the deallocation function is to be called, there is no longer an object to provide a virtual lookup mechanism but the lookup rules ensure that operator delete
has a dynamic (virtual-lite!) lookup mechanism. This means that operator delete can sensibly be static
without losing touch with the original object's dynamic type.
delete
operator is for deallocating memory only, and memory is deallocated for the most derived class object as a whole - in one action - exactly the same way as with new
operator it is allocated for the whole most-derived class object - the object of class passed as argument into new Class
construct.
This is why when you do delete ptr;
the delete
operator is always called only once for the actual most-derived class of the object being deleted and the data on what class it is is deduced from either the vtable if the virtual destructor is present or the type of the pointer if there's no virtual destructor. That's why there'no implicit virtualness to the delete
operator - all virtualness ends at the point of destructor call.
精彩评论