Operator new and delete on Inherited class. Operator delete not executing

Viewed 739

I was messing around operator overloading and I've noticed that on inherited object, the overloaded operator delete doesn't seem to execute when the inherited object has an operator new overloaded:

#include <iostream>
#include <string>

class TestAbs {
public:
  TestAbs (void) {
  }
  virtual ~TestAbs (void) noexcept {
  }
};

class Test : public TestAbs {
public:
  Test (void) 
      : TestAbs () {
  }
  ~Test (void) noexcept override {
  } 
  void* operator new (size_t) throw () {
    std::cout << "Overloaded operator new!\n";
    return nullptr;
  }
  void operator delete (void*) noexcept {
    std::cout << "Overloaded operator delete in class: Test!\n";
  }
};

int main() {
    TestAbs* tp = new Test ();
    delete tp;

    return 0;
}

The code above has the following output:

Overloaded operator new!

What happened to the overloaded operator delete? Thank you all in advance!

Update: Thank you guys for all the help. It seems like the problem was indeed the nullptr return on the overloaded new.

2 Answers

Deleting a nullptr is always a no-op in C++14 and later. Nothing gets called. To make your example work, you'd need to return a pointer that is not null. For example:

void* operator new(size_t) throw()
{
    std::cout << "Overloaded operator new!\n";
    return ::new Test;
}

From cppreference:

If expression evaluates to a null pointer value, no destructors are called, and the deallocation function is not called.

The above is for C++14 and later. Up to C++11, the deallocation function might get called. It's implementation-defined:

If expression evaluates to a null pointer value, no destructors are called, and the deallocation function may or may not be called (it's implementation-defined), but the default deallocation functions are guaranteed to do nothing when handed a null pointer.

Your code should work, if you just return an address that isn't null pointer value. To quote the C++ standard:

[class.free]/4

Class-specific deallocation function lookup is a part of general deallocation function lookup ([expr.delete]) and occurs as follows. If the delete-expression is used to deallocate a class object whose static type has a virtual destructor, the deallocation function is the one selected at the point of definition of the dynamic type's virtual destructor ([class.dtor]).

[class.dtor]/13

At the point of definition of a virtual destructor (including an implicit definition), the non-array deallocation function is determined as if for the expression delete this appearing in a non-virtual destructor of the destructor's class (see [expr.delete]). If the lookup fails or if the deallocation function has a deleted definition, the program is ill-formed. [ Note: This assures that a deallocation function corresponding to the dynamic type of an object is available for the delete-expression ([class.free]).  — end note ]

[expr.delete]/6

If the value of the operand of the delete-expression is not a null pointer value, the delete-expression will invoke the destructor (if any) for the object or the elements of the array being deleted.

You just set it up in a way that won't invoke anything at the delete expression. I fixed it up to forward onto the global operators new and delete, and everything works as expected. The code is on Coliru Viewer.

Related