8 Expressions [expr]

8.3 Unary expressions [expr.unary]

8.3.5 Delete [expr.delete]

delete-expressionОператор разрушает most derived object или массив , созданный new-expression.

delete-expression:
	::opt delete cast-expression
	::opt delete [ ] cast-expression

Первый вариант предназначен для объектов, не являющихся массивами, а второй - для массивов. Всякий раз, когда за delete ключевым словом сразу следуют пустые квадратные скобки, оно должно интерпретироваться как вторая альтернатива.81 Операнд должен иметь указатель на тип объекта или тип класса. Если тип класса, операнд contextually implicitly converted указывает на тип объекта.82 В delete-expressionрезультате «S имеет тип void.

Если операнд имеет тип класса, операнд преобразуется в тип указателя путем вызова вышеупомянутой функции преобразования, и преобразованный операнд используется вместо исходного операнда в оставшейся части этого раздела. В первой альтернативе (delete object) значением операнда delete может быть значение нулевого указателя, указатель на объект, не являющийся массивом, созданный предыдущим new-expression, или указатель на, subobject представляющий base class такой объект. В противном случае поведение не определено. Во второй альтернативе (delete array) значение операнда delete может быть значением нулевого указателя или значением указателя, полученным в результате предыдущего массива new-expression.83 В противном случае поведение не определено. [ Note: Это означает, что синтаксис delete-expressionдолжен соответствовать типу выделенного объекта new, а не синтаксису new-expression. ] [ Указатель на тип может быть операндом a ; в выражении указателя нет необходимости перед его использованием в качестве операнда . ]end noteNote: const delete-expressioncast away the constnessdelete-expressionend note

В первой альтернативе (delete object), если статический тип удаляемого объекта отличается от его динамического типа, статический тип должен быть базовым классом динамического типа удаляемого объекта, а статический тип должен иметь виртуальный тип. деструктор или поведение не определено. Во второй альтернативе (delete array), если динамический тип удаляемого объекта отличается от его статического типа, поведение не определено.

cast-expressionВ delete-expressionдолжна быть оценена только один раз.

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

Если значение операнда delete-expressionне является значением нулевого указателя, delete-expressionон вызовет деструктор (если есть) для объекта или элементов удаляемого массива. В случае с массивом элементы будут уничтожены в порядке убывания адреса (то есть в порядке, обратном завершению их конструктора; см. [class.base.init]).

Если значение операнда delete-expressionне является значением нулевого указателя, то:

  • Если вызов выделения для new-expressionудаляемого объекта не был пропущен и выделение не было расширено ([expr.new]), delete-expressionобъект должен вызвать a deallocation function. Значение, возвращаемое из вызова распределения, new-expressionдолжно быть передано в качестве первого аргумента функции освобождения.

  • В противном случае, если выделение было расширено или было предоставлено путем расширения выделения другого new-expression, и delete-expressionдля каждого другого значения указателя, созданного a, new-expressionкоторый имел хранилище, предоставленное расширенным new-expression, было оценено, то delete-expressionдолжен вызвать функцию освобождения. Значение, возвращаемое из вызова распределения расширенного, new-expression должно быть передано в качестве первого аргумента функции освобождения.

  • В противном случае delete-expressionфункция освобождения памяти не будет вызвана.

[ Note: Функция освобождения вызывается независимо от того, генерирует ли деструктор для объекта или какого-либо элемента массива исключение. ] Если значение операнда является значением нулевого указателя, не указано, будет ли вызываться функция освобождения, как описано выше.end notedelete-expression

[ Note: Реализация предоставляет определения по умолчанию operator delete для функций глобального освобождения для не-массивов ([new.delete.single]) и operator delete[] для массивов ([new.delete.array]). Программа на C ++ может предоставлять альтернативные определения этих функций ([replacement.functions]) и / или версии для конкретных классов ([class.free]). ]end note

Когда ключевому слову delete в a delete-expressionпредшествует унарный ​::​ оператор, имя функции освобождения ищется в глобальной области. В противном случае поиск учитывает функции освобождения, специфичные для класса ([class.free]). Если не найдена зависящая от класса функция освобождения, имя функции освобождения ищется в глобальной области видимости.

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

  • Если тип имеет выравнивание "новый-расширенный", std​::​align_­val_­t предпочтительнее использовать функцию с параметром типа ; в противном случае предпочтительнее использовать функцию без такого параметра. Если найдена ровно одна предпочтительная функция, выбирается эта функция, и процесс выбора завершается. Если найдено более одной предпочтительной функции, все нежелательные функции исключаются из дальнейшего рассмотрения.

  • Если функции освобождения имеют область видимости класса, std​::​size_­t выбирается функция без параметра типа .

  • Если тип является полным и если только для второй альтернативы (удалить массив), операнд является указателем на тип класса с нетривиальным деструктором или его (возможно, многомерным) массивом, функция с параметром тип std​::​size_­t выбран.

  • В противном случае не указано, std​::​size_­t выбрана ли функция освобождения с параметром типа .

Когда delete-expression выполняется a , выбранная функция освобождения должна вызываться с адресом наиболее производного объекта в delete object случае или адресом объекта, соответствующим образом скорректированным с учетом накладных расходов на выделение массива ([expr.new]) в delete array случае, в качестве ее первого аргумента. Если используется функция освобождения с параметром типа std​::​align_­val_­t , выравнивание типа удаляемого объекта передается как соответствующий аргумент. Если используется функция освобождения с параметром типа std​::​size_­t , размер наиболее производного типа или массива плюс накладные расходы на выделение соответственно передается в качестве соответствующего аргумента.84 [ Note: Если это приводит к вызову обычной функции освобождения памяти, и либо первый аргумент не был результатом предыдущего вызова обычной функции распределения, либо второй аргумент не был соответствующим аргументом в указанном вызове, поведение не определено ([new.delete.single], [new.delete.array]). ]end note

Контроль доступа и неоднозначности выполняется как для функции освобождения, так и для деструктора ([class.dtor], [class.free]).

Лямбда-выражение lambda-introducer, состоящее из пустых квадратных скобок, может следовать за delete ключевым словом, если лямбда-выражение заключено в круглые скобки.

Это означает, что объект нельзя удалить с помощью указателя типа, void* поскольку void он не является типом объекта.

Для массивов ненулевой длины это то же самое, что указатель на первый элемент массива, созданного им new-expression. Массивы нулевой длины не имеют первого элемента.

Если статический тип удаляемого объекта полный и отличается от динамического типа, а деструктор не виртуальный, размер может быть неправильным, но этот случай уже не определен, как указано выше.