Операции распределения памяти
В языке C++ для управления динамической памятью введены операции new и delete (для массивов new [ ] и delete [ ]). В С для этого применялись в C++, однако новые операции имеют некоторые преимущества.
Переопределение операций new и delete
Стандартные (глобальные) версии операций new и delete можно переопределить или перегрузить, чтобы придать им некоторые дополнительные свойства или обеспечить возможность передачи им дополнительных аргументов. Это бывает полезно при отладке, когда требуется проследить все выделения и освобождения динамической памяти:
#include <stdlib.h>
#include <stdio.h>
////////////////////////////////////////////////////
/ / Переопределение операций new и delete.
//
void* operator new(size_t size)
{
printf("%u bytes requested.\n", size);
return malloc(size);
void operator delete(void *ptr)
{
printf("Delete performed.\n") ;
free(ptr) ;
}
/////////////////////////////////////////////////////////////
// Перегрузка new для выдачи дополнительной информации.
//
void* operator new (size t size, char *file, int line)
printf("%u bytes requested in file %s line %d.\n", size, file, line) ;
return malloc(size);
}
int main(void) {
double *dptr = new double; // Вызывает новую new.
*dptr = 3.14159265;
delete dptr; // Вызывает новую delete.
// Вызов перегруженной new.
dptr = new(_FILE_, _LINE_) double;
*dptr = 1.0;
delete dptr;
return 0;
}
Здесь используется механизм определения функций-операций C++. В этом языке можно переопределить или перегрузить практически любое обозначение операции, чтобы, например, можно было применять стандартные знаки арифметических операций к объектам созданных пользователем типов. Об этом мы будем говорить в следующих главах.
Обратите внимание на синтаксис определения и вызова функций-операций new и delete. Операция new должна возвращать пустой указатель, а ее первым параметром всегда является число затребованных байтов. Компилятор автоматически вычисляет это число в соответствии с типом создаваемого объекта. Возвращаемый указатель приводится к этому типу.
Перегруженная версия new может быть, кстати, определена таким образом, что она не будет выделять никакой новой памяти, а будет использовать уже существующий объект. Адрес, где нужно разместить “новый” объект, должен быть одним из дополнительных параметров функции-операции. Эта форма new известна как синтаксис размещения (placement syntax).
Размещающая форма new полезна, если требуется вызвать конструктор класса для уже существующего объекта или организовать какую-то специальную схему управления памятью.
Операция delete имеет тип void, а ее параметр — void*.
Обработка ошибок
В C++ имеется библиотечная функция 5et_new_handler().Он будет вызываться при любой ошибке выделения памяти.
#include <stdlib.h>
#include <stdio.h>
#include <new.h>
void MyHandler(void)
{
prir-tf("No memory!\n");
exit(l) ;
}
int main(void) {
set_new_handler (MyHandler) ; //Установка обработчика.
return 0;
}
Обработчик ошибок new должен:
Заключение
Теперь вы знаете о ряде конструкций языка C++, которые можно рассматривать в качестве модификаций старого С, не вносящих ничего принципиально нового. Принципиально новое начнется со следующей главы, где мы перейдем к классам и объектно-ориентированному программированию.