Заглавная страница Избранные статьи Случайная статья Познавательные статьи Новые добавления Обратная связь 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; просмотров: 283; Нарушение авторского права страницы; Мы поможем в написании вашей работы! infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 18.218.76.193 (0.008 с.) |