Это поведение undefined для удаления указателя null void *?
Я знаю, что delete
с нулевым указателем является no-op:
В любой альтернативе, если значение операнда delete является нулевым указателем, операция не действует.
(С++ Standard 5.3.5 [expr.delete] p2
)
А также, что удаление указателя void*
- это поведение undefined, потому что деструктор не может быть вызван, поскольку нет объектов типа void
:
В первом альтернативе (delete object
) значение операнда delete должно быть указателем на объект без массива или указателем на под-объект, представляющий базовый класс такого объекта. Если нет, поведение undefined.
(С++ Standard 5.3.5 [expr.delete] p2
)
Теперь, как правило, я считаю, что вещи, которые перечислены, сначала перенаправляют вещи, которые перечислены позже, но как насчет указателя null void*
следующим образом?
void* p = 0;
delete p; // UB or well-defined?
Ответы
Ответ 1
Интересно, как вы можете достичь ситуации, когда вы удаляете указатель, только если он равен нулю. Но пребывание в режиме адвокации языка...
В С++ 03
5.3.5/1
операнд delete должен иметь тип указателя или тип класса, имеющие одно преобразование в тип указателя.
void * - это тип указателя, так что указатель null void отвечает статическому требованию.
5.3.5/2
В любой альтернативе [ delete
и delete[]
], если значение операнда удаления является нулевым указателем, операция не имеет эффекта.
И это дает желаемое поведение.
5.3.5/3
В первом альтернативе (удалить объект), если статический тип операнда отличается от его динамического типа, статический тип должен быть базовым классом динамического типа операнда, а статический тип должен иметь виртуальный деструктор или поведение undefined.
Это не имеет значения, нулевой указатель не ссылается на объект, на котором можно проверить дополнительное ограничение.
В С++ 0X
5.3.5/1
Операнд должен иметь указатель на тип объекта или тип класса, имеющий одну неявную функцию преобразования (12.3.2), на указатель на тип объекта.
void * не является указателем на тип объекта, поэтому его следует отклонить.
Ответ 2
В §5.3.5/3 говорится:
В первом варианте (удалить объект), если статический тип операнд отличается от его динамического тип, статический тип должен быть базовым класс динамических типов операндов и статический тип должен иметь виртуальный деструктор или поведение undefined. Во втором варианте (удалить массив), если динамический тип объект, подлежащий удалению, отличается от его статический тип, поведение undefined 73
В сноске говорится:
73 - Это означает, что объект не может быть удален с помощью указателя типа void *, потому что нет объектов типа void.
Так что да, его UB.
Теперь, когда он входит в город поведения undefined, не имеет значения, является ли его нулевым или нет, поскольку его поведение не может оставаться четко определенным по той причине, что он уже получил место жительства в городе undefined.
EDIT:
Появилась другая тема, которая также цитирует ее и говорит, что ее UB:
Можно ли удалить указатель на void?
Ответ 3
Я верю в его поведение undefined. new void
не разрешено (вам не разрешено создавать объекты типа void
), поэтому вызов delete
на void*
тоже не имеет смысла. Не имеет значения, указывает ли он на NULL
или нет. Я никогда не буду использовать такую вещь в моем коде.