Почему удаление 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 *
также.