Сначала я думал, что это неопределенное поведение.
5.3.5 / 3: «Во втором варианте ( удалить массив ), если динамический
тип объекта, который будет удален
отличается от своего статического типа, то
поведение не определено. 73) .
Сноска 73 гласит: «Это означает, что объект нельзя удалить с помощью указателя типа void*
, поскольку нет объектов типа void
».
Возможно, объект в вашем примере не имеет динамический тип, поскольку определение «динамический тип» в 1.3.3 упоминает «наиболее производный объект» и определение «наиболее производный объект» «На 1.8 / 4 идет речь об объектах классового типа. Поэтому я продолжал искать:
5.2.10 / 3: "[reinterpret_cast] может или не может создавать представление
отличается от первоначального значения "
5.3.5 / 2: «Значение операнда delete
должно быть значением указателя
который возник из предыдущего массива
новое выражение ».
Я не уверен, приводит ли reinterpret_cast к тому же значению указателя, которое было введено, или нет. Возможно, это прояснилось с помощью какого-то другого стандарта, который я еще не нашел. Я бы не назвал этот код «ОК», не найдя что-то, чтобы окончательно утверждать, что если вы повторно интерпретируете указатель, результат будет таким же «значением указателя», как и раньше, так что, передавая его в delete [], вы передаете «значение указателя "из нового [].
5.2.10 / 7: «За исключением того, что приведение [между определенными типами указателей] и
вернуться к своему первоначальному типу дает
исходное значение указателя, результат
такое преобразование указателя
не определены».
Это выглядит как плохая новость для меня - это явно не говорит о том, что приведение дает одинаковое значение, только то, что пара приведений назад и назад дает одинаковое значение. Это наводит меня на мысль, что один бросок может давать другое значение, но это только намекающий, а не явный. Это обычная проблема с правилом «если стандарт не устанавливает поведение, то поведение не определено». То, что оно не указано ни в одном из абзацев, которые я могу найти с помощью индекса, не означает, что оно не указано где-то еще ...
Мы знаем, что на практике мы можем приводить вещи к unsigned char * для проверки их байтов или void * для копирования POD с использованием memcpy, поэтому должны быть гарантированы некоторые приведения для создания псевдонимов. Вы можете подумать, что если ваша реализация создает псевдонимы с определенными приведениями, то вы передаете «то же значение», которое вы получили от new []. Но я все еще не уверен, что этого достаточно для удаления []. Я думаю, что упускаю что-то важное.