Пространства имён
Варианты
Действия

Выражение delete

Материал из cppreference.com
< cpp‎ | language
 
 
Язык С++
Общие темы
Управление потоком
Операторы условного выполнения
if
Операторы итерации (циклы)
Операторы перехода
Функции
Объявление функции
Выражение лямбда-функции
Спецификатор inline
Спецификации динамических исключений (до C++17*)
Спецификатор noexcept (C++11)
Исключения
Пространства имён
Типы
Спецификаторы
decltype (C++11)
auto (C++11)
alignas (C++11)
Спецификаторы длительности хранения
Инициализация
Выражения
Альтернативные представления
Литералы
Логические - Целочисленные - С плавающей запятой
Символьные - Строковые - nullptr (C++11)
Определяемые пользователем (C++11)
Утилиты
Атрибуты (C++11)
Types
Объявление typedef
Объявление псевдонима типа (C++11)
Casts
Неявные преобразования - Явные преобразования
static_cast - dynamic_cast
const_cast - reinterpret_cast
Выделение памяти
Выражение delete
Классы
Свойства функции класса
explicit (C++11)
static
Специальные функции-элементы
Шаблоны
Разное
 
Выражения
Общие
Категории значений (lvalue, rvalue, xvalue)
Порядок оценки (точки последовательности)
Константные выражения
Потенциально оцениваемые выражения
Первичные выражения
Лямбда-выражения(C++11)
Литералы
Целочисленные литералы
Литералы с плавающей запятой
Логические литералы
Символьные литералы, включая управляющие последовательности
Строковые литералы
Литерал нулевого указателя(C++11)
Пользовательский литерал(C++11)
Операторы
a=b, a+=b, a-=b, a*=b, a/=b, a%=b, a&=b, a|=b, a^=b, a<<=b, a>>=b
++a, --a, a++, a--
+a, -a, a+b, a-b, a*b, a/b, a%b, ~a, a&b, a|b, a^b, a<<b, a>>b
a||b, a&&b, !a
a==b, a!=b, a<b, a>b, a<=b, a>=b, a<=>b (начиная с C++20)
a[b], *a, &a, a->b, a.b, a->*b, a.*b
a(...), a,b, a?b:c
выражение new
выражение delete
выражение throw
alignof
sizeof
sizeof...(C++11)
typeid
noexcept(C++11)
Выражения свёртки(C++17)
Альтернативные представления операторов
Приоритет и ассоциативность
Перегрузка операторов
Сравнение по умолчанию(C++20)
Преобразования
Неявные преобразования
Обычные арифметические преобразования
const_cast
static_cast
reinterpret_cast
dynamic_cast
Явные преобразования: (T)a, T(a), auto(a), auto{a} (начиная с C++23)
Пользовательское преобразование
 

Уничтожает объект(ы), ранее выделенный выражением new, и освобождает полученную область памяти.

Содержание

[править] Синтаксис

::(необязательно) delete    выражение (1)
::(необязательно) delete [] выражение (2)
выражение дно из следующих:
1) Уничтожает один объект, не являющийся массивом, созданный выражением new
2) Уничтожает массив, созданный выражением new[]

[править] Объяснение

Дан указатель, оценённый из выражения (после возможных преобразований) как ptr.

1) ptr должен быть одним из
  • нулевым указателем,
  • указателем на объект, не являющийся массивом, созданный с помощью выражения new, или
  • указатель на базовый подобъект объекта, не являющегося массивом, созданного выражением new.
Тип, на который указывает ptr, должен быть аналогичен типу объекта (или базового подобъекта). Если ptr что-то другое, в том числе если это указатель, полученный выражением new формы массива, поведение неопределено.
2) ptr должен быть нулевым указателем или указателем, значение которого ранее было получено с помощью выражения new формы массива, чья функция распределения памяти не была формой без выделения памяти (т.е. перегрузкой (10)).
Тип, на который указывает ptr, должен быть подобным типу элемента объекта массива. Если ptr что-то другое, в том числе если это указатель, полученный выражением new не формы для массивов, поведение неопределено.

Результат выражения удаления всегда имеет тип void.

Если удаляемый объект имеет неполный тип класса в момент удаления, а полный класс имеет нетривиальный деструктор или функцию освобождения памяти, поведение не определено.

Если ptr не является нулевым указателем и функция освобождения не является уничтожающим удалением (начиная с C++20), выражение delete вызывает деструктор (если есть) для уничтожаемого объекта или для каждого элемента уничтожаемого массива (от последнего элемента к первому элементу массива).

После этого, независимо от того, было ли выброшено исключение каким-либо деструктором, выражение delete вызывает функцию освобождения памяти: либо operator delete (для первой версии выражения) или operator delete[] (для второй версии выражения), если соответствующее выражение new не было объединено с другим выражением new (начиная с C++14).

Имя функции освобождения памяти ищется в области видимости динамического типа объекта, на который указывает ptr, что означает, что функции освобождения памяти для конкретного класса, если они есть, будут найдены до глобальных. Если :: присутствует в выражении delete, этот поиск проверяет только глобальное пространство имён. В любом случае любые объявления, кроме обычных функций освобождения памяти, отбрасываются.

Если поиск находит более одной функции освобождения памяти, вызываемая функция выбирается следующим образом (смотрите функцию освобождения памяти для более подробного описания этих функций и их эффектов):

  • Если хотя бы одна из функций освобождения памяти является разрушающим удалением, все неразрушающие удаления игнорируются.
(начиная с C++20)
  • Если требования к выравниванию типа превышают __STDCPP_DEFAULT_NEW_ALIGNMENT__, предпочтительны функции освобождения памяти с учётом выравнивания (с параметром типа std::align_val_t). Для других типов предпочтительны функции освобождения памяти без учёта выравнивания (без параметра типа std::align_val_t).
  • Если найдено более одной предпочтительной функции, на следующем этапе рассматриваются только предпочтительные функции.
  • Если предпочтительные функции не найдены, на следующем шаге рассматриваются непредпочтительные.
  • Если остается только одна функция, выбирается она.
(начиная с C++17)
  • Если найденные функции освобождения памяти относятся к классу, предпочтительнее использовать функцию освобождения памяти, не учитывающую размер класса (без параметра типа std::size_t), чем функцию освобождения памяти, зависящую от класса (с параметром типа std::size_t).
  • Иначе поиск достиг глобальной области видимости и:
  • Если тип полный и если, только для формы массива, операнд является указателем на тип класса с нетривиальным деструктором или его (возможно, многомерным) массивом, выбирается глобальная функция. с учётом размера (с параметром типа std::size_t)
  • Иначе не указано, будет ли выбрана глобальная функция освобождения памяти с учётом размера (с параметром типа 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)

[править] Ключевые слова

delete

[править] Отчёты о дефектах

Следующие изменения поведения были применены с обратной силой к ранее опубликованным стандартам 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[]
запрещено

[править] Смотрите также