C++. Бархатный путь. Часть 2 - Функции operator new() и operator delete()
ОГЛАВЛЕНИЕ
Функции operator new() и operator delete()
Время жизни объекта определяется областью действия его имени. В зависимости от расположения оператора определения объекта, он может располагаться в глобальном или локальном сегменте памяти. При определении глобального объекта соответствующие конструкторы объявляются со спецификатором public, поскольку они должны быть доступны фактически до начала выполнения программы. Глобальные объекты существуют в течение всего времени выполнения программы.
Локальные объекты создаются в соответствующих сегментах памяти в ходе выполнения операторов определения, после передачи управления в функцию или вложенный блок операторов. По возвращении из вложенного блока или функции, имя объекта оказывается вне области действия имени. Сам же объект уничтожается в момент освобождения соответствующего сегмента памяти. Важная роль при этом отводится деструкторам.
Можно избежать преждевременной гибели объекта, расположив его в динамической памяти. В этом случае память для объекта выделяется с помощью выражения размещения. Значением этого выражения является адрес области памяти, выделенной для размещения объекта в результате выполнения выражения. Очевидно, что это значение можно присвоить переменной типа указатель на объект данного класса.
Динамическая память не опустошается автоматически. "Гибель" локального указателя, настроенного на выделенную область динамической памяти означает всего лишь потерю доступа к этой области памяти. В этом случае уничтожается указатель, но освобождения памяти не происходит.
Для освобождения памяти используется операция (операторная функция) delete. Подобно операторной функции new, delete также является статическим членом класса.
В контексте выражений размещения и удаления могут быть использованы стандартные операции C++ new и delete, а может быть обеспечен вызов операторных функций operator new и operator delete.
Согласно грамматике C++, основным операндом для символа операции new в выражении размещения является заключённое в круглые скобки ИмяТипа, либо ИмяТипаNew (без скобок), которое разворачивается в конструкцию, содержащую информацию о размерах размещаемого массива (константные выражения в квадратных скобках):
ВыражениеРазмещения
::= [::] new [Размещение] ИмяТипаNew [ИнициализаторNew]
::= [::] new [Размещение] (ИмяТипа) [ИнициализаторNew]
ИмяТипаNew ::= СписокСпецификаторовТипа [ОписательNew]
ОписательNew ::= [СписокCVОписателей] [ОписательNew]
::= [ОписательNew] [Выражение]
::= *****
При этом можно определить несколько различных вариантов операторной функции operator new. Перегруженные операторные функции будут различаться списками параметров. В C++ предусмотрены специальные средства передачи значений параметров подобным перегруженным операторным функциям. С этой целью используется так называемое Размещение, которое является необязательным составным элементом выражения размещения. Заключённый в круглые скобки список выражений располагается в выражении размещения непосредственно перед именем операторной функции new.
Мы объявляем простой класс, содержащий определения операторных функций распределения динамической памяти. И размещаем это объявление в заголовочном файле с именем TypeX.h.
// TypeX.h
#ifndef TYPEX
#define TYPEX
/*
Инструкции препроцессора используются для предотвращения многократного
объявления класса в программном модуле.
Даже если в исходном файле появится несколько инструкций препроцессора,
обеспечивающих включение заголовочного файла TypeX.h, в исходном файле
окажется всего лишь одно объявление класса TypeX.
*/
// Объявление класса TypeX.
class TypeX
{
public:
/* Встроенный конструктор */
TypeX() { cout << "Это TypeX()" << endl; }
/* Встроенный конструктор с параметром */
TypeX(int x) { cout << "Это TypeX(" << x << ")" << endl; }
/* Встроенный деструктор */
~TypeX() { cout << "Это ~TypeX()" << endl; }
/* Встроенная операторная функция operator new() */
void *operator new(size_t size)
{
cout << "Это void *operator new(" << size << ")" << endl;
return new char(size);
}
/* Операторная функция operator new() с дополнительным параметром */
void *operator new(size_t size, int xPar)
{
cout << "void *operator new(" << size << "," << xPar << ")" << endl;
return new char(size);
}
/* Встроенная операторная функция operator delete() */
void operator delete(void *cPoint, size_t size)
{
cout << "Это void operator delete(" << size << ")" << endl;
if (cPoint) delete cPoint;
};
};
#endif