11 Classes [class]

11.11 Free store [class.free]

Any allocation function for a class T is a static member (even if not explicitly declared static).
[Example 1: class Arena; struct B { void* operator new(std::size_t, Arena*); }; struct D1 : B { }; Arena* ap; void foo(int i) { new (ap) D1; // calls B​::​operator new(std​::​size_­t, Arena*) new D1[i]; // calls ​::​operator new[](std​::​size_­t) new D1; // error: ​::​operator new(std​::​size_­t) hidden } — end example]
Any deallocation function for a class X is a static member (even if not explicitly declared static).
[Example 2: class X { void operator delete(void*); void operator delete[](void*, std::size_t); }; class Y { void operator delete(void*, std::size_t); void operator delete[](void*); }; — end example]
Since member allocation and deallocation functions are static they cannot be virtual.
[Note 1:
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.
For example, struct B { virtual ~B(); void operator delete(void*, std::size_t); }; struct D : B { void operator delete(void*); }; struct E : B { void log_deletion(); void operator delete(E *p, std::destroying_delete_t) { p->log_deletion(); p->~E(); ::operator delete(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​::​operator delete(), and the object of class E is destroyed and its storage is deallocated by E​::​operator delete(), due to the virtual destructor.
— end note]
[Note 2:
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.
For example, struct B { virtual ~B(); void operator delete[](void*, std::size_t); }; struct D : B { void operator delete[](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 note]
Access to the deallocation function is checked statically, even if a different one is actually executed.
[Example 3:
For the call on line “// 1” above, if B​::​operator delete() had been private, the delete expression would have been ill-formed.
— end example]
[Note 3:
If a deallocation function has no explicit noexcept-specifier, it has a non-throwing exception specification ([except.spec]).
— end note]