Операции класса new и delete
Класс может определять свои собственные операции new и delete (new[] и delete [] для массива объектов):
Ниже приведен довольно длинный пример, демонстрирующий определение операций класса new и delete, а также глобальных new [ ] и delete []. Вывод программы позволяет проследить порядок вызовов конструкторов/деструкторов и операций new/delete при создании автоматических и динамических объектов.
Листинг 8.1. Определение операций класса new и delete
//////////////////////////////////////////////
// NewDel.cpp: Операции класса new и delete.
//
#pragma hdrstop
#include <condefs.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define trace(msg)
printf(#msg "\n")
#define MaxStr 32
void *operator new[](size_t size)
// Замена глобальной
// new[].
{
trace(Global new [ ] .);
return malloc(size);
}
void operator delete[](void *p)
// Замена глобальной
// delete[].
{
trace(Global delete [].);
free(p) ;
}
class Hold {
char *str;
// Закрытый указатель на строку.
public:
Hold(const char*) ;
~Hold() ;
void *operator new(size t);
// Операция new класса.
void operator delete(void*);
// Операция delete класса.
void Show(void)
{ printf("%s\n", str);
}
};
Hold::Hold(const char *s)
// Конструктор.
{
trace (Constructor.) ;
str = new char[MaxStr];
// Вызов глобальной new[].
strncpy(str, s, MaxStr);
// Копирование строки в объект.
str[MaxStr-1] = 0;
// На всякий случай...
}
Hold::~Hold ()
// Деструктор.
{
trace(Destructor.);
delete[] str;
// Очистка объекта.
}
void *Hold::operator new(size_t size)
{
trace(Class new.);
return malloc (size);
)
void Hold::operator delete(void *p)
{
trace(Class delete.);
free(p) ;
)
void Func()
// Функция с локальным объектом.
{
Hold funcObj ("This is a local object in Func.");
funcObj.Show() ;
}
int main () {
Hold *ptr;
Hold mainObj ("This is a local object in main.");
mainObj.Show ();
trace (*);
ptr = new Hold("This is a dynamic object.");
ptr->Show();
delete ptr;
trace (*);
FuncO ;
trace (*);
return 0;
}
Результат работы программы показан на рис. 8.1.
Рис. 8.1 Программа NewDel
Пример заодно поясняет, зачем нужен деструктор. Здесь он удаляет динамически созданную строку, адрес которой хранится в объекте. Если не определить деструктор, то генерированный компилятором деструктор по умолчанию удалит сам объект, но не строку, которая окажется “потерянной”. Подобные упущения являются распространенной причиной утечек памяти.