C++ Программирование в среде С++ Builder 5

         

Операции класса new и delete


Класс может определять свои собственные операции new и delete (new[] и delete [] для массива объектов):

  • Функция имя_класса: : operator new () вызывается при создании динамических объектов.
  • Функция имя_класса: : operator new [ ] () вызывается при создании динамических массивов объектов.
  • Функция имя_класса:: operator delete() вызывается при удалении динамических объектов.
  • Функция имя_класса:: operator 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



    Пример заодно поясняет, зачем нужен деструктор. Здесь он удаляет динамически созданную строку, адрес которой хранится в объекте. Если не определить деструктор, то генерированный компилятором деструктор по умолчанию удалит сам объект, но не строку, которая окажется “потерянной”. Подобные упущения являются распространенной причиной утечек памяти.


    Содержание раздела