Question

I am using c++11 (g++ v4.7.2)

I've overloaded operator new and operator delete for "Base" class. Apparently they should not call constructor/destructor upon call of new/delete because I've not implemented ctor/dtor call in overloaded new/delete. But the output is contrary to that

//Output of below program
Base new opnd.cpp 87
Base ctor
10
Base dtor
Base delete

Why ctor/dtor are being called for overloaded operator new/delete?

#include <iostream>

using namespace std;

#define NEW new(__FILE__, __LINE__)
#define DELETE delete

class Base
{
    public:
        Base():m_i(10){ cout << "Base ctor" << endl; }
        virtual ~Base(){ cout << "Base dtor" << endl; }

        void* operator new(size_t size, const char* file, int line) throw(std::bad_alloc);
        void operator delete(void *rawMem, size_t size);

        int geti(){ return m_i; }

    private:
        int m_i;
};

void* Base::operator new(size_t size, const char* file, int line) throw(std::bad_alloc)
{
    void *p;
    cout << "Base new " << file << " " << line << endl;

    //Handle 0 byte requests
    if(size == 0)
        size = 1;

    if(size != sizeof(Base))
    {
        return ::operator new(size);       // To handle new requests for derived classes
    }

    while(true)
    {
        p = malloc(size);

        if(p)
            return p;

        new_handler globalHandler = set_new_handler(0);
        set_new_handler(globalHandler);
        if(globalHandler) (*globalHandler)();
        else throw std::bad_alloc();
    }
}

void Base::operator delete(void *rawMem, size_t size)
{
    cout << "Base delete" << endl;
    if(rawMem == 0)
        return;

    if(size != sizeof(Base))
    {
        ::operator delete(rawMem);     //To handle delete requests for derived classes
        return;
    }

    free(rawMem);
}

int main()
{
   Base *b = NEW Base;
   cout << b->geti() << endl;
   DELETE b;

   return 0;
}
Was it helpful?

Solution

An operator new function (be it the global one or a class-specific one) is not the entire implementation of a new expression. It's only the allocation function. When you write new T in your code, the following happens:

  1. An appropriate allocation function named operator new is chosen and called to obtain space for the object.

  2. T's constructor is called on the space obtained from point 1.

This means there is no way to bypass constructor invocation by writing your own operator new - invoking the constructor is done by the language, not by the allocation function.

OTHER TIPS

'Operator new' and 'new Operator' are two distinct things. When we use new to create some object like

     MyClass* ca= new MyClass();

we are using the 'new Operator'. It does two things:

  1. Calls 'Operator new' to allocate enough memory. It can be overloaded as you did.
  2. Calls the constructor of the object to set initialization data.

These 2 steps will be executed no matter how the space is allocated. Hence after allocating memory using your overloaded 'Operator new', the constructor is called.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top