• Welcome to Valhalla Legends Archive.
 

[C++] Overloading new and delete operators

Started by NeBuR, March 01, 2004, 10:39 AM

Previous topic - Next topic

NeBuR

Hello. This time, I've been trying to overload the new and delete operators, in both simple and array versions. Let's take a look to the source code, and then I'll expose my question.

First of all, here are my new and delete overloaded global operators:
static void * operator new (size_t numBytes)
{
   cerr << "operator new (" << numBytes << ")" << endl;

   void * memory = (void *)malloc(numBytes);
//   void * memory = ::operator new(numBytes);

   return(memory);
}

static void * operator new[] (size_t numBytes)
{
   cerr << "operator new [] (" << numBytes << ")" << endl;

   void * memory = (void *)malloc(numBytes);
//   void * memory = ::operator new(numBytes);

   return(memory);
}

static void operator delete (void * memory)
{
   cerr << "operator delete (" << memory << ")" << endl;
   free(memory);
//   ::delete(memory);
}

static void operator delete[] (void * memory)
{
   cerr << "operator delete [] (" << memory << ")" << endl;
   free(memory);
//   ::delete(memory);
}


Then, here is the simple class written in order to prove the operators:
class MyClass
{
public:
   ~MyClass () { cerr << "MyClass::~MyClass()" << endl; DecObjectCount(); }
   MyClass () : mValue(0) { cerr << "MyClass::MyClass()" << endl; IncObjectCount(); }

   static int GetObjectCount () { return(mObjectCount); }

private:
   int mValue;
   static int mObjectCount;

   static void IncObjectCount () { mObjectCount++; }
   static void DecObjectCount () { mObjectCount--; }
};

int MyClass::mObjectCount = 0;


And last, the main function:
int main (int argn, char ** argv)
{
   {
      cout << endl << "Inicialization:" << endl;
      cout << MyClass::GetObjectCount() << " MyClass objects" << endl;
   }

   {
      cout << endl << "Dynamically allocated single object:" << endl;
      MyClass *   ptrObject = new MyClass;
      cout << MyClass::GetObjectCount() << " MyClass objects" << endl;
      delete ptrObject;
      cout << MyClass::GetObjectCount() << " MyClass objects" << endl;
   }

   {
      cout << endl << "Dynamically allocated object array:" << endl;
      MyClass *   ptrObjects = new MyClass[10];
      cout << MyClass::GetObjectCount() << " MyClass objects" << endl;
      delete [] ptrObjects;
      cout << MyClass::GetObjectCount() << " MyClass objects" << endl;
   }

   {
      cout << endl << "Dynamically allocated single float:" << endl;
      float * ptrFloat = new float;
      delete ptrFloat;
   }

   {
      cout << endl << "Dynamically allocated float array:" << endl;
      float * ptrFloats = new float[10];
      delete [] ptrFloats;
   }

   return(0);
}


This is the output of the program:
Inicialization:
0 MyClass objects

Dynamically allocated single object:
operator new (4)
MyClass::MyClass()
1 MyClass objects
MyClass::~MyClass()
operator delete (268548824)
0 MyClass objects

Dynamically allocated object array:
MyClass::MyClass()
MyClass::MyClass()
MyClass::MyClass()
MyClass::MyClass()
MyClass::MyClass()
MyClass::MyClass()
MyClass::MyClass()
MyClass::MyClass()
MyClass::MyClass()
MyClass::MyClass()
10 MyClass objects
MyClass::~MyClass()
MyClass::~MyClass()
MyClass::~MyClass()
MyClass::~MyClass()
MyClass::~MyClass()
MyClass::~MyClass()
MyClass::~MyClass()
MyClass::~MyClass()
MyClass::~MyClass()
MyClass::~MyClass()
0 MyClass objects

Dynamically allocated single float:
operator new (4)
operator delete (268548824)

Dynamically allocated float array:
operator new [] (40)
operator delete [] (268550448)


Well, I ask for the reason that makes the overloaded new[] operator to be called when creating an array of floats, but not when creating an array of MyClass objects. As you can see, the overloaded new operator works fine in both cases. The same occurs with the overloaded delete operators.

I've compiled this source with CC MIPSpro 7.30 for IRIX, and the output shown has been generated with this version. I've tried the same source code with Micro$oft Visual C++ 6.0, and surprisingly :P it doesn't produce the same output. With Visual C++, the overloaded new[] operator works fine with both object and float arrays.

A secondary question is about the impossibility of using the scope operator to access the original versions of both new and delete operators from the overloaded ones' function bodies.

I've tried with operators overloaded inside the class itself, and all works fine. But I'm asking this because I need to overload the global operators as I've described here.

I don't know what the standar says about this, and I hope that you can help me with this. Sorry if my English is hard to understand. Once again, thank you very much for your time :)

NeBuR

Without the static keyword, my overloaded delete[] operator is used when destroying the MyClass objects array, but not the overloaded new[] one, and I don't understand why.

I've tried now the same with placement new operators, that is, those which have extra parameters, because they are those which I want to use in practice:

void * new (size_t size, void * place);
void * new[] (size_t size, void * place);
void delete (void * memory, void * place);
void delete[] (void * memory, void * place);


It's allowed to include any number of adittional parameters of any type. The overloaded new and delete operators implementations are the same I showed in the previous post, while the extra parameter is (for now) not used.

Now, the overloaded placement operator new[] works fine, even with arrays of objects. There are, however, two problems with the placement operators delete and delete[]. First, it's not allowed to extend the delete call syntax in this logic form:

MyClass * ptrObject = new(myPlace) MyClass;
MyClass * ptrObjects = new(myPlace) MyClass[10];

delete(myPlace) ptrObject;
delete(myPlace) [] ptrObjects;


Instead, we must use the explicit operator call syntax:

operator delete (ptrObject, myPlace);
operator delete[] (ptrObjects, myPlace);


Well, this seems only a question of appereance. But the second problem is a burden problem, and I don't know if it's related to the first. Calling this overloaded placement operators delete and delete[] doesn't trigger the execution of MyClass destructor for any deleted object.

This modifications compiles with CC MIPSpro 7.30 for IRIX, and work with problems I've described. With Micro$oft Visual C++ 6.0, a run-time error appears when the overloaded placement operator delete[] calls internally free(), and the program ends its execution.