|
 |
 |
[an error occurred while processing this directive]
The following listing, ex2\newdel.cpp, is based on the previous listing, but has been extended to overload the new[] and delete[] operators as well:
// File: overnew.cpp
// Example for C++ How-To
// Shows how to overload new and delete to implement a simple memory
// statistics keeper. This example also overloads new[] and delete[] operators.
// Copyright 1998, Jan Walter
// NO WARRANTY. If this code breaks you get to keep both pieces.
// Compiler verificiation:
// Borland C++ 5.01A: Yes
// DJGPP 2.01 w. GCC 2.81 : Yes
// Microsoft VC++ 5: Not Tried
// GCC 2.7.2/Linux: Yes
// GCC/EGCS/Linux: Not tried
#include <iostream.h>
#include <fstream.h>
#include <stddef.h>
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#include <string>
#include <stdexcept> // standard exception classes
using namespace std ;
//*********************************************************************
// Memory statistics class
//*********************************************************************
class MemStats
{
private:
unsigned BytesAllocated ;
unsigned BytesDeleted ;
unsigned CallsToNew ;
unsigned CallsToDel ;
unsigned CallsToNewArray ;
unsigned CallsToDelArray ;
fstream StatsFile;
public:
MemStats() : BytesAllocated(0), BytesDeleted(0), CallsToNew(0),
CallsToDel(0), CallsToNewArray(0), CallsToDelArray(0)
{
StatsFile.open( memstats.txt, ios::out ) ;
if( !StatsFile )
throw runtime_error( Could not open memstats.txt ) ;
}
MemStats( const string& filename ) : BytesAllocated(0), BytesDeleted(0),
CallsToNew(0), CallsToDel(0), CallsToNewArray(0),
CallsToDelArray(0)
{
StatsFile.open( filename.c_str() , ios::out ) ;
if( !StatsFile )
throw runtime_error( Could not open user-defined file. ) ;
}
// these functions can be expanded to do all sorts of other things,
// like print more info into the output file, time and date, etc.
// or keep track of the allocated chunks of memory in an associative
// array.
void newcalled( size_t size )
{
CallsToNew++ ;
BytesAllocated += size ;
}
void newarraycalled( size_t size )
{
CallsToNewArray++ ;
BytesAllocated += size ;
}
void delcalled( size_t size )
{
CallsToDel++ ;
BytesDeleted += size ;
}
void delarraycalled( size_t size )
{
CallsToDelArray++ ;
BytesDeleted += size ;
}
~MemStats()
{
StatsFile << endl
<< Memory allocation statistics : << endl
<< (the numbers below should match) << endl
<< endl
<< Bytes Allocated : << BytesAllocated << endl
<< Bytes Deleted : << BytesDeleted << endl
<< Calls to new : << CallsToNew << endl
<< Calls to new[] : << CallsToNewArray << endl
<< Calls to delete : << CallsToDel << endl
<< Calls to delete[]: << CallsToDelArray << endl
<< endl ;
StatsFile.close() ; // explicitly close file to make
// doubly sure.
}
} ;
//*********************************************************************
// an interesting side note:
// we cannot easily catch exceptions thrown by the constructor of
// a global object - above the constructor throws a runtime_error
// exception object if it cannot open the file in the constructor.
// If this is true, the program will abort with some message like
// abnormal program termination or Abort!
MemStats stats ;
//*********************************************************************
// Sample Data class - nothing special, just an example
//*********************************************************************
class Sample_Data
{
int S_int ;
double S_double ;
public:
Sample_Data() : S_int(0), S_double(0.0)
{ }
Sample_Data( int a, double b = 0.0)
{
S_int = a ;
S_double = b ;
}
Sample_Data( double b, int a = 0 )
{
S_double = b ;
S_int = a ;
}
Sample_Data( Sample_Data& copyfrom )
{
S_int = copyfrom.S_int ;
S_double = copyfrom.S_double ;
}
Sample_Data& operator=( const Sample_Data& copyfrom )
{
S_int = copyfrom.S_int ;
S_double = copyfrom.S_double ;
return *this ;
}
Sample_Data& operator++()
{
S_int++ ;
return *this ;
}
void* operator new( size_t size )
{
stats.newcalled( size ) ;
return (void*) ::new char[size] ; // allocate specified number of bytes
// with the actual new operator
}
void* operator new[](size_t size )
{
stats.newarraycalled( size ) ;
return (void*) ::new char[size] ;
}
void operator delete( void* mem, size_t size )
{
stats.delcalled( size );
::delete[] mem ;
}
void operator delete[]( void* mem, size_t size )
{
stats.delarraycalled( size ) ;
::delete[] mem ;
}
// friend functions
friend ostream& operator<<( ostream& s, const Sample_Data& data );
};
//*********************************************************************
ostream& operator<<( ostream& s, const Sample_Data& data )
{
s << data.S_int << << data.S_double ;
return s ;
}
//*********************************************************************
int main( int, char** )
{
const int array_size = 25000 ;
// allocate our sample data
// declare one object
Sample_Data a( 50 , 12.555 );
// instantiate an object dynamically
Sample_Data* p = new Sample_Data( 21 ) ;
// declare an array
Sample_Data* DataArray = new Sample_Data[array_size] ;
// declare an array of pointers
Sample_Data* PDataArray[array_size] ;
// initialize the array
for (int i = 0 ; i < array_size ; i++ )
PDataArray[i] = new Sample_Data(i) ;
// Now work with the data some
DataArray[0] = a ;
for( int i = 1; i < array_size ; i++ )
{
DataArray[i] = ++DataArray[i-1] ;
//cout << DataArray[i] << endl ;
}
++*p ;
cout << *p << endl ;
// and clean up dynamically allocated stuff.
delete p ;
delete[] DataArray ;
for (int i = 0 ; i < array_size ; i++ )
delete PDataArray[i] ;
return 0;
}
// end of file
|