Подтвердить что ты не робот

Это поведение 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?
4b9b3361

Ответ 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 или нет. Я никогда не буду использовать такую ​​вещь в моем коде.