Страустрап Бьярн
Шрифт:
Результат имеет тип void. Операндом delete должен быть указатель, который возвращает new. Эффект применения операции delete к указателю, который не получен в результате операции new без задания параметры-new, считается неопределенным и обычно приводит к опасным последствиям. Однако гарантируется, что удаление по указателю с нулевым значением безопасно.
Результат попытки доступа к удаленному объекту неопределен, а удаление объекта может изменить его значение. Более того, если выражение, задающее объект, является изменяемым адресом, его значение после удаления неопределено.
Нельзя удалять указатель на константу.
Операция delete вызывает деструктор (если он есть $$12.4) для объекта, на который настроен ее операнд.
Для освобождения памяти, отведенной под указываемый объект, операция delete вызывает функцию operator delete (§R.12.5). Для объектов, не имеющих тип класс (в том числе и для массивов классов), используется глобальная функция ::operator delete. Для объекта типа класс T вызывается функция T::operator delete, если она есть (используя обычные правила просмотра при поиске членов класса и производных от него классов, §R.10.1.1), в противном случае вызывается глобальная функция::operator delete. Обращение ::delete гарантирует, что будет вызываться глобальная функция ::operator delete, даже если существует T::operator delete. Для удаления массивов используется обращение вида
Здесь выражение должно указывать на массив. Если есть деструкторы, они будут вызываться для удаления указанных объектов.
Результат удаления массива с помощью простого обращения delete неопределен, так же как и удаление одиночного объекта с помощью delete [].
R.5.4 Явное преобразование типа
Явное преобразование типа можно задать с помощью функциональной записи (§R.5.2.3) или с помощью операции приведения.
Задание с помощью операции приведения используется для обозначения преобразования к типу, который не является конструкцией имя-простого-типа.
В операции приведения нельзя определять типы.
Всякое преобразование типа, не упомянутое здесь и не являющееся преобразованием явно определенным пользователем (§R.12.3), считается ошибкой.
Любой тип, который можно преобразовать в другой с помощью стандартного преобразования (§R.4), можно также преобразовать с помощью явного преобразования (приведения) и смысл преобразования будет тот же.
Указатель можно преобразовать к любому целочисленному типу, достаточно большому, чтобы вместить значение указателя. Алгоритм преобразования зависит от реализации, но предполагается, что он будет естественным для того, кто знает систему адресации, используемой машины.
Значение целочисленного типа может быть явно преобразовано в указатель. Указатель, преобразованный в целое достаточного размера (если такие есть в реализации), и преобразованный обратно к типу указателя, должен иметь свое первоначальное значение. Все другие детали перевода указателя в целое и обратно зависят от реализации.
Указатель на объект одного типа может быть преобразован в указатель на объект другого типа (с соблюдением ограничений, указанных здесь). Использование получившегося указателя может вызвать особую адресную ситуацию ("неверный адрес"), если преобразуемый указатель не настроен на объект, правильным образом выравненный в памяти. Гарантируется, что указатель на объект данного размера можно преобразовать в указатель на объект равного или меньшего размера и провести обратное преобразование без изменения значения указателя. На различных машинах двоичное представление указателей может быть различно как и требования на выравнивания объектов. Составные объекты выравниваются по самой строгой границе, требуемой их составляющими. Указатель типа void* считается совместимым с указателем на объект любого типа.
Указатель на класс B можно преобразовать в указатель на класс D, для которого класс B является прямо или опосредованно базовым классом, если существует однозначное преобразование из D в B (§R.4.6, $$.R10.1.1) и если B является виртуальным базовым классом (§R.10.1). Такое приведение от базового класса к производному классу предполагает, что объект базового класса является вложенным по отношению к объекту производного класса. В результате получится указатель, настроенный на объемлющий объект производного класса. Если объект базового класса не содержится ни в каком объекте производного класса, такая операция приведения может вызвать особую ситуацию.
Пустой указатель (0) преобразуется сам в себя.
Пока еще неопределенный класс можно использовать в операции приведения указателя, в этом случае никаких допущений о структуре класса не делается (§R.10.1).
Любой объект можно явно преобразовать к типу ссылки X&, если указатель на этот объект можно явно преобразовать в тип X*. В результате приведения к ссылке не происходит вызовов конструкторов или функций преобразований. Преобразование ссылки на базовый класс в ссылку на производный класс рассматривается аналогично преобразованию указателя на базовый класс в указатель на производный класс, учитывая вопросы однозначности, виртуальных классов и т.д.