11 Classes [class]

11.4 Class members [class.mem]

11.4.11 Allocation and deallocation functions [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]