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

Операции распределения памяти


В языке 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 должен:

  • либо возвратить управление, освободив память;


  • либо вызвать abort () или exit ();


  • либо выбросить исключение bad_alloc или производного класса.




  • Заключение



    Теперь вы знаете о ряде конструкций языка C++, которые можно рассматривать в качестве модификаций старого С, не вносящих ничего принципиально нового. Принципиально новое начнется со следующей главы, где мы перейдем к классам и объектно-ориентированному программированию.


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