Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции / LECS14.DOC
Скачиваний:
43
Добавлен:
16.04.2013
Размер:
89.09 Кб
Скачать

Перегрузка new и delete

Большинство классов содержит операции по распределению и освобождению памя­ти. Иногда для обеспечения эффективности или надежности требуется более изощ­ренное использование памяти, чем то, которое предоставляется с помощью простого, вызова операторов new и delete.

Оператор new имеет следующий общий вид:

:: opt new размещениеopt тип инициализаторopt

Здесь optобозначает необязательные (optional) части. Вот некоторые примеры:

::new char[10]; //настаивает на глобальном new new(buff) Х(а); //вызов с buff используя X: :X(a)

До сих пор для выделения свободной памяти мы использовали глобальный оператор new (). Система неявно предоставляет аргумент sizeof (тип} для этой функции. Вот прототип функции:

void* operator new(size_t size) ;

Операторы new и delete могут быть перегружены. Это свойство предоставляет ме­ханизм, позволяющий пользователю манипулировать свободной памятью. Напри­мер, в традиционном программировании на С для доступа к свободной памяти ис­пользуется malloc (), она возвращает void* указатель на выделенную память. В этой схеме память освобождается с помощью функции free () из stdlib.h. Использу­ем перегрузку операторов new и delete, чтобы позволить объекту Х управлять сво­бодной памятью традиционным для С образом.

#include <stdlib.h> //определены malloc() и free ()

class X { public:

void* operator new(size_t size)

{ return (malloc(size)); }

void operator delete(void* ptr) { free(ptr); }

X(unsigned size) { new(size); }

~X( ) { delete(this); }

. . . . .

};

В этом примере класс X предоставляет перегруженные формы new () и delete (). Если класс перегружает operator new (), глобальный оператор по прежнему дос­тупен с помощью оператора разрешения области видимости : :.

Одна из причин по которой перегружаются эти операторы состоит в стремле­нии придать им дополнительную семантику, например, обеспечение диагностичес­кой информации или устойчивости к сбоям. Кроме того, класс может обеспечивать более эффективную схему распределения памяти чем та, которую предоставляет система.

Синтаксис размещения (placement) предоставляет разделенный запятыми список аргументов, используемый для выбора перегруженного оператора new () с соответствующей сигнатурой. Эти дополнительные аргументы часто применяются для того, чтобы поместить создаваемый объект по конкретному адресу. Такая форма операто­ра new использует заголовочный файл new.h.

В файле over_new.cpp

//Синтаксис размещения и перегруженный new

#include <iostream.h>

#include <new.h>

char* buf1 = new char[1000];//вместо свободной памяти

char* buf2 = new char[1000];

class object { public:

. . . . .

private:

. . . . .

};

int main ()

{

object *p=new(buf1) object; // размещение в buf1

object *q=new(buf2) object; // размещение в buf2

. . . . .

}

Синтаксис размещения позволяет пользователю иметь произвольную сигнатуру для перегруженного оператора new. Эта сигнатура отличается от аргументов ини­циализатора, используемых в вызове new, выбирающем соответствующий конст­руктор.

Оператор delete бывает двух видов. Он может иметь следующие сигнатуры:

void operator delete(void* p) ;

void operator delete(void* p, size_t);

Первая сигнатура не заботится о количестве байт, возвращаемых оператором delete. В этом случае программист поставляет код, предоставляющий это значе­ние. Вторая сигнатура включает аргумент size_t, передаваемый вызову delete. Он передается компилятору как размер объекта, на который указывает р. В каждом классе только одна форма delete может быть задана как статическая функция-член.

В файле new.h имеется указатель _new_handler на функцию, которая вызывает обработчик ошибок для оператора new. Если память исчерпана, указатель _new_handler используется для вызова системной процедуры. С помощью set_new_handler () пользователь может указать явную процедуру <<недостаточ-но памяти>>, которая заменит системную. Мы возвратимся к эти вопросам в разде­ле 11.2, «Использование signal.h», на стр. 315, когда будем обсуждать исключения, обработку ошибок и корректность программ.

В файле new_hdlr.cpp

//Простая отказоустойчивость с применением _new_handler

#include <new.h>

#include <stdlib.h> //для выхода

void heap_exhausted()//пользовательский

//обработчик ошибок

{

cerr « "КУЧА ИСЧЕРПАНА" « endl;

exit(1);

}

int main()

{

set_new_handler(heap_exhausted) ;

..... //истощение памяти как heap_exhausted()

}

Функции-члены new () и delete () всегда неявно статические. Функция new () вызывается до того, как объект существует и, следовательно, у него еще нет this. Функция delete() вызывается деструктором при уничтожении объекта.

8

Соседние файлы в папке Лекции