Выражение delete
Уничтожает объект(ы), ранее выделенный выражением new, и освобождает полученную область памяти.
Содержание |
[править] Синтаксис
:: (необязательно) delete выражение
|
(1) | ||||||||
:: (необязательно) delete [] выражение
|
(2) | ||||||||
выражение | — | дно из следующих:
|
[править] Объяснение
Дан указатель, оценённый из выражения (после возможных преобразований) как ptr.
- нулевым указателем,
- указателем на объект, не являющийся массивом, созданный с помощью выражения new, или
- указатель на базовый подобъект объекта, не являющегося массивом, созданного выражением new.
Результат выражения удаления всегда имеет тип void.
Если удаляемый объект имеет неполный тип класса в момент удаления, а полный класс имеет нетривиальный деструктор или функцию освобождения памяти, поведение не определено.
Если ptr не является нулевым указателем и функция освобождения не является уничтожающим удалением (начиная с C++20), выражение delete
вызывает деструктор (если есть) для уничтожаемого объекта или для каждого элемента уничтожаемого массива (от последнего элемента к первому элементу массива).
После этого, независимо от того, было ли выброшено исключение каким-либо деструктором, выражение delete вызывает функцию освобождения памяти: либо operator delete (для первой версии выражения) или operator delete[] (для второй версии выражения), если соответствующее выражение new не было объединено с другим выражением new (начиная с C++14).
Имя функции освобождения памяти ищется в области видимости динамического типа объекта, на который указывает ptr, что означает, что функции освобождения памяти для конкретного класса, если они есть, будут найдены до глобальных. Если ::
присутствует в выражении delete
, этот поиск проверяет только глобальное пространство имён. В любом случае любые объявления, кроме обычных функций освобождения памяти, отбрасываются.
Если поиск находит более одной функции освобождения памяти, вызываемая функция выбирается следующим образом (смотрите функцию освобождения памяти для более подробного описания этих функций и их эффектов):
|
(начиная с C++20) |
|
(начиная с C++17) |
- Если найденные функции освобождения памяти относятся к классу, предпочтительнее использовать функцию освобождения памяти, не учитывающую размер класса (без параметра типа std::size_t), чем функцию освобождения памяти, зависящую от класса (с параметром типа std::size_t).
|
(начиная с C++14) |
Указатель на освобождаемый блок памяти передаётся функции освобождения памяти, которая была выбрана описанным выше процессом, в качестве первого аргумента. Размер блока передаётся как необязательный аргумент std::size_t. Требование выравнивания передаётся как необязательный аргумент std::align_val_t. (начиная с C++17)
Если ptr это значение нулевого указателя, деструкторы не вызываются и функция освобождения памяти может быть вызвана или нет (не определено), но функции освобождения по умолчанию гарантир��ванно ничего не делают при передаче нулевого указателя.
Если ptr это указатель на подобъект базового класса объекта, память для которого была выделена с помощью new, деструктор базового класса должен быть virtual, в противном случае поведение не определено.
[править] Примечание
Указатель на void нельзя удалить, поскольку он не является указателем на полный тип объекта.
Поскольку пара квадратных скобок после ключевого слова delete всегда интерпретируется как форма массива выражения delete, лямбда-выражение с пустым списком захвата сразу после delete должно быть заключено в круглые скобки. // 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 1642 | C++98 | выражение может быть указателем lvalue | не допускается |
CWG 2474 | C++98 | удаление указателя на объект подобного, но другого типа приводит к неопределённому поведению |
чётко определено |
CWG 2624 | C++98 | указатели, полученные в результате нераспределяющего operator new[], могут быть переданы в delete[] |
запрещено |