Выражение delete
Уничтожает объект(ы), ранее выделенный выражением new, и освобождает полученную область памяти.
Содержание |
[править] Синтаксис
::(необязательно) delete выражение
|
(1) | ||||||||
::(необязательно) delete [] выражение
|
(2) | ||||||||
[править] Объяснение
Для первой формы (не массива) выражение должно быть указателем на объектный тип или классовый тип контекстно неявно преобразуемый к такому указателю, и его значение должно быть либо null, либо указателем на объект, не являющийся массивом, созданный выражением new, либо указателем на базовый подобъект объекта, не являющегося массивом, созданный выражением new. Тип, на который указывает выражение должен быть аналогичным типу объекта (или базового подобъекта). Если выражение является чем-то другим, в том числе если это указатель, полученный формой выражения new для массива, поведение будет неопределённым.
Для второй формы (массива) выражение должно быть нулевым значением указателя или значением указателя, ранее полученным формой выражения new для массива. Указываемый тип выражения должен быть аналогичным типу элемента объекта массива. Если выражение является чем-то другим, включая указатель, полученный формой выражения new не для массива, поведение будет неопределённым.
Результат выражения всегда имеет тип void.
Если удаляемый объект имеет неполный тип класса в момент удаления, а полный класс имеет нетривиальный деструктор или функцию освобождения памяти, поведение не определено.
Если выражение не является нулевым указателем и функция освобождения не является уничтожающим удалением (начиная с C++20), выражение delete вызывает деструктор (если есть) для уничтожаемого объекта или для каждого элемента уничтожаемого массива (от последнего элемента к первому элементу массива).
После этого, независимо от того, было ли выброшено исключение каким-либо деструктором, выражение delete вызывает функцию освобождения памяти: либо operator delete (для первой версии выражения) или operator delete[] (для второй версии выражения), если соответствующее выражение new не было объединено с другим выражением new (начиная с C++14).
Имя функции освобождения памяти ищется в области видимости динамического типа объекта, на который указывает выражение, что означает, что функции освобождения памяти для конкретного класса, если они есть, будут найдены до глобальных. Если :: присутствует в выражении delete, этот поиск проверяет только глобальное пространство имён. В любом случае любые объявления, кроме обычных функций освобождения памяти, отбрасываются.
Если поиск находит более одной функции освобождения памяти, вызываемая функция выбирается следующим образом (смотрите функцию освобождения памяти для более подробного описания этих функций и их эффектов):
|
(начиная с C++20) |
|
(начиная с C++17) |
- Если найденные функции освобождения памяти относятся к классу, предпочтительнее использовать функцию освобождения памяти, не учитывающую размер класса (без параметра типа std::size_t), чем функцию освобождения памяти, зависящую от класса (с параметром типа std::size_t)
|
(начиная с C++14) |
Указатель на освобождаемый блок памяти передаётся функции освобождения памяти, которая была выбрана описанным выше процессом, в качестве первого аргумента. Размер блока передаётся как необязательный аргумент std::size_t. Требование выравнивания передаётся как необязательный аргумент std::align_val_t. (начиная с C++17)
Если выражение оценивается как значение нулевого указателя, деструкторы не вызываются и функция освобождения памяти может быть вызвана или нет (не определено), но функции освобождения по умолчанию гарантированно ничего не делают при передаче нулевого указателя.
Если выражение оценивается как указатель на подобъект базового класса объекта, память для которого была выделена с помощью new, деструктор базового класса должен быть virtual, в противном случае поведение не определено.
[править] Примечание
Указатель на void нельзя удалить, поскольку он не является указателем на полный тип объекта.
|
Поскольку пара квадратных скобок после ключевого слова // delete []{ return new int; }(); // ошибка синтаксического анализа delete ([]{ return new int; })(); // OK |
(начиная с C++11) |
[править] Ключевые слова
[править] Отчёты о дефектах
Следующие изменения поведения были применены с обратной силой к ранее опубликованным стандартам C++:
| Номер | Применён | Поведение в стандарте | Корректное поведение |
|---|---|---|---|
| CWG 288 | C++98 | для первой формы статический тип операнда сравнивался с его динамическим типом |
сравнивается статический тип удаляемого объекта с его динамическим типом |
| CWG 353 | C++98 | будет ли вызываться функция освобождения памяти, если деструктор выдаёт исключение, не указано |
всегда вызывается |
| CWG 599 | C++98 | первая форма может принимать нулевой указатель любого типа, включая указатели на функции |
кроме указателей на типы объектов, все другие типы указателей отклоняются |
| CWG 2474 | C++98 | удаление указателя на объект подобного, но другого типа приводит к неопределённому поведению |
чётко определено |

