You rarely need to provide a custom
new or
delete , but if you need them you usually don't want to hide the built-in signatures.
In C++, after you define a name in a scope (e.g., in a class scope), it will hide the same name in all enclosing scopes (e.g., in base classes or enclosing namespaces), and overloading never happens across scopes. And when said name is
operator new , you need to be extra cautious lest you make life hard for your class's clients.
Say you define a class-specific
operator new :
class C {
// …
static void* operator new(size_t, MemoryPool&);
// hides three normal forms };
Then, if someone tries to write an expression as boring as plain old
new C , the compiler will reject it on grounds that it can't find plain old
operator new . Declaring the
C::operator new overload that takes a
MemoryPool hides all other overloads, including the familiar built-in global versions that we all know and love, to wit:
void* operator new(std::size_t);
// plain new void* operator new(std::size_t, std::nothrow_t) throw();
// nothrow new void* operator new(std::size_t, void*);
// in-place new
Alternatively, perhaps your class provides a class-specific version of one of these three operators
new . In that case, by declaring one of them your class will by default also mask the other two:
class C {
// …
static void* operator new(size_t, void*);
// hides other two normal forms };
Prefer to have class
C explicitly bring into scope all three of the standard variants of
operator new . Normally, all should have the same visibility. (The visibility can still be made
private for individual forms, such as if you want to explicitly disable the plain or non-throwing
operator new , but the purpose of this Item is to remind you not to hide them inadvertently.)
Note that you should always avoid hiding in-place
new because STL containers use it extensively.
The only remaining trick is that exposing the hidden operators
new needs to be done in two different ways in two different circumstances. If your class's base class also defines
operator new , all you need to do to "unhide"
operator new is:
class C : public B {
// … public:
using B::operator new; };
Otherwise, if there is no base class version or the base class doesn't define
operator new , you will need to write some short forwarding functions (because you can't employ
using to pull names from the global namespace):
class C {
// … public: static void* operator new(std::size_t s) { return ::operator new(s); } static void* operator new(std::size_t s, std::nothrow_t nt) throw() { return ::operator new(s, nt); } static void* operator new(std::size_t s, void* p) { return ::operator new(s, p); } };
The advice above also applies to the array forms of
operator new[] and
operator delete[] .
Avoid calling the
new (nothrow) version in client code, but provide it to save some clients from surprises if they happen to use it.