Any deallocation function for a class
X
is a static member (even if not explicitly declared
static).
[Example 2: class X {voidoperatordelete(void*);
voidoperatordelete[](void*, std::size_t);
};
class Y {voidoperatordelete(void*, std::size_t);
voidoperatordelete[](void*);
};
— end example]
However, when the
cast-expression
of a
delete-expression
refers to an object of class type with a virtual destructor,
because the deallocation function is chosen by the destructor
of the dynamic type of the object, the effect is the same in that case.
[Example 3: struct B {virtual~B();
voidoperatordelete(void*, std::size_t);
};
struct D : B {voidoperatordelete(void*);
};
struct E : B {void log_deletion();
voidoperatordelete(E *p, std::destroying_delete_t){
p->log_deletion();
p->~E();
::operatordelete(p);
}};
void f(){
B* bp =new D;
delete bp; // 1: uses D::operator delete(void*)
bp =new E;
delete bp; // 2: uses E::operator delete(E*, std::destroying_delete_t)}
Here, storage for the object of class
D
is deallocated by
D::operatordelete(),
and
the object of class E is destroyed
and its storage is deallocated
by E::operatordelete(),
due to the virtual destructor.
Virtual destructors have no effect on the deallocation function actually
called when the
cast-expression
of a
delete-expression
refers to an array of objects of class type.
[Example 4: struct B {virtual~B();
voidoperatordelete[](void*, std::size_t);
};
struct D : B {voidoperatordelete[](void*, std::size_t);
};
void f(int i){
D* dp =new D[i];
delete[] dp; // uses D::operator delete[](void*, std::size_t)
B* bp =new D[i];
delete[] bp; // undefined behavior} — end example]