Follow Techotopia on Twitter

On-line Guides
All Guides
eBook Store
iOS / Android
Linux for Beginners
Office Productivity
Linux Installation
Linux Security
Linux Utilities
Linux Virtualization
Linux Kernel
System/Network Admin
Programming
Scripting Languages
Development Tools
Web Development
GUI Toolkits/Desktop
Databases
Mail Systems
openSolaris
Eclipse Documentation
Techotopia.com
Virtuatopia.com
Answertopia.com

How To Guides
Virtualization
General System Admin
Linux Security
Linux Filesystems
Web Servers
Graphics & Desktop
PC Hardware
Windows
Problem Solutions
Privacy Policy

  




 

 

Thinking in C++
Prev Contents / Index Next

Overloading global new & delete

This is the drastic approach, when the global versions of new and delete are unsatisfactory for the whole system. If you overload the global versions, you make the defaults completely inaccessible – you can’t even call them from inside your redefinitions.

The overloaded new must take an argument of size_t (the Standard C standard type for sizes). This argument is generated and passed to you by the compiler and is the size of the object you’re responsible for allocating. You must return a pointer either to an object of that size (or bigger, if you have some reason to do so), or to zero if you can’t find the memory (in which case the constructor is not called!). However, if you can’t find the memory, you should probably do something more informative than just returning zero, like calling the new-handler or throwing an exception, to signal that there’s a problem.

The return value of operator new( ) is a void*, not a pointer to any particular type. All you’ve done is produce memory, not a finished object – that doesn’t happen until the constructor is called, an act the compiler guarantees and which is out of your control.

The operator delete( ) takes a void* to memory that was allocated by operator new. It’s a void* because operator delete only gets the pointer after the destructor is called, which removes the object-ness from the piece of storage. The return type is void.

Here’s a simple example showing how to overload the global new and delete:

//: C13:GlobalOperatorNew.cpp
// Overload global new/delete
#include <cstdio>
#include <cstdlib>
using namespace std;

void* operator new(size_t sz) {
  printf("operator new: %d Bytes\n", sz);
  void* m = malloc(sz);
  if(!m) puts("out of memory");
  return m;
}

void operator delete(void* m) {
  puts("operator delete");
  free(m);
}

class S {
  int i[100];
public:
  S() { puts("S::S()"); }
  ~S() { puts("S::~S()"); }
};

int main() {
  puts("creating & destroying an int");
  int* p = new int(47);
  delete p;
  puts("creating & destroying an s");
  S* s = new S;
  delete s;
  puts("creating & destroying S[3]");
  S* sa = new S[3];
  delete []sa;
} ///:~

Here you can see the general form for overloading new and delete. These use the Standard C library functions malloc( ) and free( ) for the allocators (which is probably what the default new and delete use as well!). However, they also print messages about what they are doing. Notice that printf( ) and puts( ) are used rather than iostreams. This is because when an iostream object is created (like the global cin, cout, and cerr), it calls new to allocate memory. With printf( ), you don’t get into a deadlock because it doesn’t call new to initialize itself.

In main( ), objects of built-in types are created to prove that the overloaded new and delete are also called in that case. Then a single object of type S is created, followed by an array of S. For the array, you’ll see from the number of bytes requested that extra memory is allocated to store information (inside the array) about the number of objects it holds. In all cases, the global overloaded versions of new and delete are used.

Thinking in C++
Prev Contents / Index Next

 
 
   Reproduced courtesy of Bruce Eckel, MindView, Inc. Design by Interspire