Почему удаление void* является UB, а не ошибкой компиляции?

Зачем удалять объект через void* быть неопределенным поведением, а не ошибкой компиляции?

void foo(void* p) {
    delete p;
}

Этот код компилирует и производит код, хотя и с предупреждением о gcc и clang (удивительно, что ICC не выдает предупреждение):

: 2: 5: предупреждение: невозможно удалить выражение с указателем на тип 'void' 'void *' [-Wdelete-incomplete]

Почему не просто неправильно сформированная программа с неверным синтаксисом? Похоже, Standard не тратит на это слишком много времени, [expr.delete] тот

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

Будет ли какая-то причина, по которой мне не хватает, почему это не вызывает серьезную ошибку компиляции?

1 ответ

Решение

В современном C++ удаление void * указатель плохо сформирован (т.е. это то, что мы обычно называем "ошибкой компиляции")

8.3.5 Удалить
1 [...] Операнд должен иметь указатель на тип объекта или тип класса.

void * не является указателем на тип объекта.

В C++98 ситуация была иной. Удаление нулевого указателя void * тип был NOP при удалении ненулевого указателя void * Тип был UB.

Это изменение в спецификации, по-видимому, было вызвано сообщением о дефекте № 599. Исходная спецификация позволяла указывать нулевые указатели любого типа указателя в выражении удаления, например, указатели на функции. Это выглядело излишне разрешающим. Постановление DR № 599 ужесточило требования, объявив вне закона void * также.

Другие вопросы по тегам