Заглавная страница Избранные статьи Случайная статья Познавательные статьи Новые добавления Обратная связь FAQ Написать работу КАТЕГОРИИ: ТОП 10 на сайте Приготовление дезинфицирующих растворов различной концентрацииТехника нижней прямой подачи мяча. Франко-прусская война (причины и последствия) Организация работы процедурного кабинета Смысловое и механическое запоминание, их место и роль в усвоении знаний Коммуникативные барьеры и пути их преодоления Обработка изделий медицинского назначения многократного применения Образцы текста публицистического стиля Четыре типа изменения баланса Задачи с ответами для Всероссийской олимпиады по праву
Мы поможем в написании ваших работ! ЗНАЕТЕ ЛИ ВЫ?
Влияние общества на человека
Приготовление дезинфицирующих растворов различной концентрации Практические работы по географии для 6 класса Организация работы процедурного кабинета Изменения в неживой природе осенью Уборка процедурного кабинета Сольфеджио. Все правила по сольфеджио Балочные системы. Определение реакций опор и моментов защемления |
Перегрузка и управление памятьюСодержание книги
Поиск на нашем сайте В программах, написанных на ANSI С, используются функции malloc() и free() вместе с им подобными библиотечными функциями для выделения и освобождения блоков памяти в куче. в программах, написанных на C++, используются операторы new и delete. На самом деле, в большинстве реализаций C++ new и delete скрыто реализуются вызовами функций mallocO и freeO. Поэтому некоторые программисты на C++ не видят для себя особой разницы между способами управления памятью в ANSI Сив C++. Однако подобное предположение таит в себе опасность, поскольку new и delete на самом деле операторы, а не функции. Как операторы, new и delete могут перегружаться с целью задания новых возможностей управления памятью для объектов класса. С помощью перегрузки new и delete вы можете получить полный контроль над операциями выделения памяти объектам. ПРЕДУПРЕЖДЕНИЕ Никогда не вызывайте функцию free() для освобождения памяти, выделяемой с помощью оператора new, и никогда не вызывайте mallocO для выделения памяти, освобождаемой позднее с помощью delete. Использование способов управления распределением памяти ANSI С и C++ вперемежку может в некоторых случаях сработать, однако программа, скорее всего, будет завершаться аварийно, если new и delete перегружаются в классе или если Borland изменит внутреннюю реализацию этих операторов в будущих версиях компилятора. Перегрузка оператора new Вы можете перегружать new точно так же, как и операторы, подобные + и =. Перегрузка new в объявлении класса указывает компилятору, что отныне на вас лежит ответственность за поддержку запросов выделения памяти для объектов этого класса. Для перегрузки new следует использовать прототип функции вида void * operator new(size_t size);. В дальнейшем обращения к оператору new для выделения памяти объектам класса будут перенаправлены перегруженнойфункции. Функция должна возвращать адрес области памяти, выделенной объекту. Если необходимого свободного пространства нет, функция должна возвращать null (нуль). В листинге 4.7 приводится простой, но полный пример перегрузки оператора new для выделения памяти объектам. Вместо кучи программа запоминает их в глобальном буфере. Можно применить аналогичный трюк для выделения памяти объектам в других местах, например на диске или другом запоминающем устройстве. ЗАМЕЧАНИЕ В строке 6 OVERNEW.CPP приводится команда #pragma warn -aus. Она предписывает компилятору выключить предупреждение о том, что в программе не используются переменные, объявленные исключительно в демонстрационных целях. Функция перегрузки оператора new, объявленная в строке 13 и реализованная в строках 38-48, проверяет наличие пространства в глобальном буфере. Если его нет, функция возвращает 0, что является основанием для возвращения оператором new значения null. (В программе не проверяется это условие, но, конечно, вы должны проверять его в реальных приложениях.) Если свободное пространство есть, глобальный индекс увеличивается на размер запрашиваемой памяти, который передается функции в параметре size. Затем функция возвращает адрес выделяемого участка памяти. Листинг 4.7. OVERNEW.CPP (перегрузка new) //4_7.cpp #include <iostream.h> #include <conio.h> // Следующая директива "pragma" выключает //предупреждение компилятора о том, что // в программе объявляются и не используются //демонстрационные переменные #pragma warn -aus class BNew { private: int x; public: BNew(); // Функция перегрузки оператора new void * operator new(size_t size); }; char buf[512]; int index=0; main() { cout << "\nCreating local instance"; BNew b1; cout << "\nAllocating space via new"; BNew *b2 = new BNew; BNew *b3 = new BNew; BNew *b4 = new BNew; BNew *b5 = new BNew; getch(); return 0; } BNew::BNew() { cout << "\n constructor"; x = index; } void *BNew::operator new(size_t size) { cout << "\n lnside overloaded new. Size = "<< size; if (index >= 512 - sizeof(BNew)) {getch(); return 0;} else { int k = index; index += sizeof(BNew); return &buf[k]; }} Перегрузка delete Оператор delete — обратная сторона медали распределения памяти. Можно перегрузить оператор delete для отслеживания удаления объектов, адресованных указателями. Прототип функции перегрузки оператора delete должен иметь вид void operator delete(void *p); где р ссылается на удаляемый объект. В качестве альтернативы можно объявить функцию следующим образом: void operator delete(void *p, size_t size); В соответствии с вторым объявлением C++ будет дополнительно передавать функции число байтов в удаляемом объекте. Для добавления функции перегрузки оператора delete в класс BNew в модуле OVERNEW (листинг 4.7) объявить функцию-член в открытой секции класса: void BNew::operator delete(void *p) cout << "\nDeleting object at " «p; Оператора вывода отображает адрес каждого удаляемого объекта. Поскольку объекты в программе не запоминаются в куче, перегруженный оператор delete на самом деле не освобождает никакой памяти. также потребуется несколько операторов для удаления нескольких объектов. Вставьте следующие строки в функцию mainO непосредственно перед оператором return: delete Ь2; delete ЬЗ; delete Ь4; delete Ь5; //4_7А.cpp #include <iostream.h> #include <conio.h> class BNew { private: int x; public: BNew(); void * operator new(size_t size); void operator delete(void *p); }; char buf[512]; int index=0; main() { clrscr(); cout << "\nCreating local instance"; BNew b1; cout << "\nAllocating space via new"; BNew *b2 = new BNew; BNew *b3 = new BNew; BNew *b4 = new BNew; BNew *b5 = new BNew; delete b2; delete b3; getch(); return 0; } BNew::BNew() { cout << "\nlnside constructor"; x = index; } void *BNew::operator new(size_t size) { //cout << "\nlnside overloaded new. Size = "<< size; //cout << "\n index = "<< index; if (index >= (512 - sizeof(BNew))) {getch(); return 0;} else { int k = index; index += sizeof(BNew); //cout << "\n k = "<< k; return &buf[k]; } } void BNew::operator delete(void *p) { cout << "\n delete "<< p; }
Этот пример приведен только для демонстрации, поскольку в полноценном приложении перегруженный оператор delete должен освобождать удаленные блоки памяти для последующего использования их перегруженным new. ЗАМЕЧАНИЕ Чтобы использовать средства управления памятью C + + для выделения пространства в куче для объектов, в которых перетружен оператор new, поставьте перед оператором двойное двоеточие. Например, и строке BNew *х =::new BrandNew игнорируется перегруженный в объектах класса BNew оператор new. Аналогично,::delete служит для обращения к оператору delete, используемому по умолчанию. Установка обработчика ошибок оператора new Обычно, если new не может выполнить запрос выделения памяти, оператор возвращает null. Для того чтобы изменить действия, предпринимаемые по умолчанию в этом случае, в C++ следует присвоить адрес функции-обработчика ошибок указателю _new__handler, определенному следующим образом: typedef void (*vfp)(void); vfp _new_handler; Использование typedef не обязательно, но оно облегчает чтение объявления. Функция-обработчик ошибок ничего не возвращает и не имеет аргументов, она устанавливается с помощью вызова функции set_new_handler(), прототип которой содержится в файле NEW.H: vfp set_new_handler(vfp); Обработчик ошибок реализуется так же, как и обычная функция C++. Например, аварийно завершить программу с сообщением об ошибке нехватки памяти: void memerr(void) { fputs("\n\nOut of memory\n", stderr); exit(1); } Для того чтобы функция memerrO вызывалась в случае возникновения ошибок, связанных с нехваткой памяти, передайте адрес memerr функции set_new_handler() следующим образом; set_new_handler(memerr); ЗАМЕЧАНИЕ Смотри также описание set_jiew_handler() в книге Освоение Borland C++. Энциклопедия функций.
|
||
|
Последнее изменение этой страницы: 2016-08-01; просмотров: 368; Нарушение авторского права страницы; Мы поможем в написании вашей работы! infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 216.73.216.214 (0.008 с.) |