X Tutup
The Wayback Machine - https://web.archive.org/web/20221103184733/https://ru.cppreference.com/w/cpp/language/delete
Пространства имён
Варианты
Действия

Выражение delete

Материал из cppreference.com
< cpp‎ | language
 
 
Язык С++
Общие темы
Управление потоком
Операторы условного выполнения
if
Операторы итераций (циклы)
Операторы переходов
Функции
Объявление функции
Выражение лямбда-функции
Спецификатор inline
Спецификации динамических исключений (до C++20)
Спецификатор noexcept (C++11)
Исключения
Пространства имён
Типы
Спецификаторы
decltype (C++11)
auto (C++11)
alignas (C++11)
Спецификаторы длительности хранения
Инициализация
Выражения
Альтернативные представления
Литералы
Логические - Целочисленные - С плавающей запятой
Символьные - Строковые - nullptr (C++11)
Определённые пользователем (C++11)
Утилиты
Атрибуты (C++11)
Типы
Объявление typedef
Объявление псевдонима типа (C++11)
Приведения
Неявные преобразования - Явные преобразования
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)
Пользовательское преобразование
 

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

Содержание

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

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

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

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

Для второй формы (массива) выражение должно быть нулевым значением указателя или значением указателя, ранее полученным формой выражения new для массива. Указываемый тип выражения должен быть аналогичным типу элемента объекта массива. Если выражение является чем-то другим, включая указатель, полученный формой выражения new не для массива, поведение будет неопределённым.

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

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

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

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

Имя функции освобождения памяти ищется в области видимости динамического типа объекта, на который указывает выражение, что означает, что функции освобождения памяти для конкретного класса, если они есть, будут найдены до глобальных. Если :: присутствует в выражении 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)

Если выражение оценивается как значение нулевого указателя, деструкторы не вызываются и функция освобождения памяти может быть вызвана или нет (не определено), но функции освобождения по умолчанию гарантированно ничего не делают при передаче нулевого указателя.

Если выражение оценивается как указатель на подобъект базового класса объекта, память для которого была выделена с помощью new, деструктор базового класса должен быть virtual, в противном случае поведение не определено.

[править] Примечание

Указатель на void нельзя удалить, поскольку он не является указателем на полный тип объекта.

Поскольку пара квадратных скобок после ключевого слова 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 2474 C++98 удаление указателя на объект подобного, но другого типа приводит
к неопределённому поведению
чётко определено

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

X Tutup