выражение delete
Уничтожает объекты, ранее выделенные выражением new, и освобождает полученную область памяти.
Синтаксис
::(необязательно) delete expression | (1) | |
::(необязательно) delete[] expression | (2) |
| expression | - | одно из следующего:
|
Пояснение
Пусть указатель, полученный в результате вычисления expression (после возможных преобразований), обозначен как ptr.
ptr должен быть одним из следующих: - нулевой указатель,
- указатель на объект, не являющийся массивом, созданный выражением new, или
- указатель на базовый подобъект объекта, не являющегося массивом, созданного выражением new.
ptr, должен быть подобен типу объекта (или базового подобъекта). Если ptr имеет любое другое значение, в том числе если это указатель, полученный с помощью массивной формы выражения new, поведение является неопределённым.ptr должен быть нулевым указателем или указателем, значение которого ранее было получено с помощью массивной формы выражения new, функция выделения памяти которого не была невыделяющей (то есть перегрузкой (10)).ptr, должен быть подобен типу элемента объекта-массива. Если ptr имеет любое другое значение, в том числе если это указатель, полученный с помощью не-массивной формы выражения new, поведение является неопределённым.Результат выражения delete всегда имеет тип void.
Если в точке удаления объект имеет неполный тип класса, а полный класс имеет нетривиальный деструктор или функцию освобождения памяти, поведение является неопределённым(до C++26)программа некорректна(начиная с C++26).
Если ptr не является нулевым указателем и функция освобождения памяти не является уничтожающим delete(начиная с C++20), выражение delete вызывает деструктор (если он есть) уничтожаемого объекта либо каждого элемента уничтожаемого массива (от последнего элемента к первому). Деструктор должен быть доступен в точке появления выражения delete.
После этого, независимо от того, было ли выброшено исключение каким-либо деструктором, выражение delete вызывает функцию освобождения памяти: либо operator delete (первая форма), либо operator delete[] (вторая форма), если только соответствующее выражение new не было объединено с другим выражением new(начиная с C++14).
Имя функции освобождения памяти ищется в области видимости динамического типа объекта, на который указывает ptr; это означает, что при наличии функций освобождения памяти, специфичных для класса, они находятся раньше глобальных. Если в выражении delete присутствует ::, при этом поиске рассматривается только глобальное пространство имён. В любом случае все объявления, кроме объявлений обычных функций освобождения памяти, отбрасываются.
Если найдена какая-либо функция освобождения памяти, вызываемая функция выбирается следующим образом (подробное описание этих функций и их эффектов см. в разделе функция освобождения памяти):
| (начиная с C++20) |
| (начиная с C++17) |
- Если найденные функции освобождения памяти являются специфичными для класса, предпочтение отдаётся специфичной для класса функции освобождения памяти, не учитывающей размер (без параметра типа
std::size_t), а не специфичной для класса функции, учитывающей размер (с параметром типаstd::size_t).
| (начиная с C++14) |
Выбранная функция освобождения памяти должна быть доступна в точке появления выражения delete, если только функция освобождения памяти не выбирается в точке определения динамического типа виртуального деструктора.
Указатель на освобождаемый блок памяти передаётся первым аргументом выбранной описанным выше способом функции освобождения памяти. Размер блока передаётся как необязательный аргумент std::size_t. Требование выравнивания передаётся как необязательный аргумент std::align_val_t.(начиная с C++17)
Если ptr имеет значение нулевого указателя, деструкторы не вызываются, а функция освобождения памяти может быть вызвана или не вызвана (это не определено), однако гарантируется, что стандартные функции освобождения памяти ничего не делают при получении нулевого указателя.
Если ptr является указателем на базовый подобъект объекта, выделенного с помощью new, деструктор базового класса должен быть виртуальным, иначе поведение является неопределённым.
Примечания
Указатель на void нельзя удалить, поскольку он не является указателем на объектный тип.
| Поскольку пара квадратных скобок после ключевого слова delete всегда интерпретируется как массивная форма выражения delete, лямбда-выражение с пустым списком захвата сразу после delete необходимо заключать в скобки. // delete []{ return new int; }(); // parse error
delete ([]{ return new int; })(); // OK
| (начиная с C++11) |
Ключевые слова
Отчёты об ошибках
Следующие отчёты об ошибках, изменяющие поведение, были ретроактивно применены к ранее опубликованным стандартам C++.
| Отчёт об ошибке | Применяется к | Опубликованное поведение | Корректное поведение |
|---|---|---|---|
| CWG 288 | C++98 | для первой формы статический тип операнда сравнивался с его динамическим типом | сравнивать статический тип удаляемого объекта с его динамическим типом |
| CWG 353 | C++98 | не было определено, будет ли вызвана функция освобождения памяти, если деструктор выбросит исключение | вызывается всегда |
| CWG 599 | C++98 | первая форма могла принимать нулевой указатель любого типа, включая указатели на функции | все остальные типы указателей, кроме указателей на объектные типы, отклоняются |
| CWG 1642 | C++98 | expression могло быть lvalue-указателем | не допускается |
| CWG 2474 | C++98 | удаление указателя на объект подобного, но отличающегося типа приводило к неопределённому поведению | поведение стало определённым |
| CWG 2624 | C++98 | указатели, полученные с помощью невыделяющего operatornew[], можно было передавать в delete[] | запрещено |
| CWG 2758 | C++98 | было неясно, как применялся контроль доступа к функции освобождения памяти и деструктору | внесена ясность |
См. также
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/language/delete