In C, malloc and similar functions are used for dynamic memory allocation. These routines however are not awares of certain data types, they only work with blocks of bytes. C++ introduces new operators called new and delete for dynamically allocating memory.
The main difference between the C and C++ methods is that new will call a classes constructor, and delete will call a classes destructor, where malloc and free will not. There is also no 'realloc' counterpart to new and delete, you must manual re-allocate memory yourself.
The new operator returns a pointer to a dynamically created object or fundamental data type. Since it an operator, and not a function, there are no parenthesis used, instead the type of data desired is placed after the new keyword. For example, imagine Date is a class:
Date * Birthday; //No constructor invoked for a pointer. char * Name; // pointer to a fundamental data type, not a class int * IP; //new will invoke the default constructor for Date Birthday = new Date; Name = new char[100] // allocate 100 chars, no constructor IP = new int;
new gives back 0 if it fails. This is technically the same value as NULL, from C, but it is more common to check for 0 because of the way that C++ deals with pointers to different types. Important: See Exception Handling below for more details.
if( Birthday == 0 ) cout << "Error";
The delete operator calls the destructor for an object and then frees the objects memory.
delete Birthday; delete [] Name; //Note that for an array, [] should //proceed the pointer name delete IP;
Since new and delete are operators, classes have the ability to over-ride them, and take control of the creation and destroying processes. This is not always required due to the nature of the constructor/destructor invoking, but the ability is there.
According to the 1997 ANSI C++ standard, the new operator should
throw an exception when out of memory, it should not return NULL
or zero. Visual C++ versions 5 and 6 still return NULL ny default
however. The code presented below will make the new operator
work more like its standard definition:
#include <new> #include <new.h> int my_new_handler(size_t) { throw std::bad_alloc(); return 0; } int main () { _PNH _old_new_handler; _ old_new_handler = _set_new_handler(my_new_handler); /* Your application code goes here */ _set_new_handler(_old_new_handler); return( 0 ); }
A typical example for using exception handling to test for an allocation failure would be:
try { char * p = new char[999999999]; } catch( bad_alloc a) { cout << a.what() << endl; return( -1 ); // further error handling } // Continue and use p
You can write new and delete operators for your class. When you do so, keep in mind that the operators will static functions, meaning they can not be virtual as well. There is no need to include the static keyword in their declaration, it is implied. In the new and delete operators for your class, you need only allocate and release the needed memory, the constructors and destructors are called automatically before after new, and before delete.
An example of a class with overloaded new and delete operators might be:
class MDate { public: MDate() { M = D = Y = 0; } int M, D, Y; void *operator new(size_t Size) { return( malloc( Size ) ); } void operator delete( void* Pntr) { free( Pntr ); } void *operator new[]( size_t Size ) { return( malloc(Size) ) ; } void operator delete[]( void* Pntr) { free( Pntr ); } };
Note: overloading new and delete are usually intended for providing
an alternative for normal memory allocation, such as a virtual
memory management scheme, or other optimized memory system. They
are not typically written for classes.