Фактически здесь три этапа: сначала выражение вызывает библиотечную функцию operator new()
(или operator new[]()
). Эта функция резервирует не типизированную область памяти достаточного размера для содержания объекта (или массива объектов) определенного типа. Затем компилятор запускает соответствующий конструктор, чтобы создать объект (объекты) из переданных инициализаторов. И наконец, возвращается указатель на вновь зарезервированный и созданный объект.
Выражение delete
применяется для удаления динамически созданного объекта:
delete sp; //
//
delete [] arr; //
Здесь два этапа: сначала для объекта, на который указывает указатель sp
, или для элементов массива, на который указывает имя arr
, выполняется соответствующий деструктор. Затем компилятор освобождает память, вызвав библиотечную функцию operator delete()
или operator delete[]()
соответственно.
Приложения, которые собираются самостоятельно контролировать распределение памяти, определяют собственные версии функций operator new()
и operator delete()
. Даже при том, что библиотека содержит определения этих функций, вполне можно определить их собственные версии, и компилятор не пожалуется на двойное определение. Вместо этого компилятор использует пользовательскую версию, а не определенную библиотекой.
operator new()
и operator delete()
вся ответственность за динамическое распределение памяти ложится на разработчика. Эти функции
Функции operator new()
и operator delete()
можно определить в глобальной области видимости или как функции-члены. Когда компилятор встречает выражение new
или delete
, он ищет соответствующую вызову функцию оператора. Если резервируемый (освобождаемый) объект имеет тип класса, то компилятор ищет сначала в пределах класса, включая все его базовые классы. Если у класса есть функции-члены operator new()
и operator delete()
, эти функции и используются в выражении new
или delete
. В противном случае компилятор ищет соответствующую функцию в глобальной области видимости. Если компилятор находит пользовательскую версию функции, он ее и использует для выполнения выражения new
или delete
. В противном случае используется версия из стандартной библиотеки.
Чтобы заставить выражение new
или delete
обойти функцию, предоставленную классом, и использовать таковую из глобальной области видимости, можно использовать оператор области видимости. Например, выражение ::new
имеет в виду функцию operator new()
только из глобальной области видимости. Аналогично для выражения ::delete
.
operator new()
и operator delete()
Библиотека определяет восемь перегруженных версий функций operator new()
и operator delete()
. Первые четыре версии оператора new
способны передавать исключение bad_alloc
. Следующие четыре версии оператора new
не передают исключений:
//
void *operator new(size_t); //
void *operator new[](size_t); //
void *operator delete(void*) noexcept; //
void *operator delete[](void*) noexcept; //
//
void *operator new(size_t, nothrow_t&) noexcept;
void *operator new[](size_t, nothrow_t&) noexcept;
void *operator delete(void*, nothrow_t&) noexcept;
void *operator delete[](void*, nothrow_t&) noexcept;