Ответ 1
В стандарте указано ([expr.delete]/5):
Если удаляемый объект имеет неполный тип класса в точке удаления, а полный класс имеет нетривиальный деструктор или функцию освобождения, поведение undefined.
Итак, если T
имеет нетривиальный деструктор или имеет перегрузку operator delete
, вы получаете UB. Ничего не сказано о том, что UB основан на значении указателя (то есть: является ли он нулевым указателем или нет).
Что означает "объект, удаляемый"?
Можно считать, что "объект, удаляемый" означает, что это предложение применяется только к вызовам delete
для реальных объектов. И поэтому, если вы передаете нулевой указатель, он не применяется.
Во-первых, в остальной части стандартного обсуждения поведения delete
явно указано, что его поведение не применяется к нулевым указателям. [expr.delete]/6 & 7 оба начинаются с "Если значение операнда выражения-удаления не является значением нулевого указателя". В пункте 5 явно не содержатся эти слова. Поэтому мы должны предположить, что оно применимо к нулевым указателям.
Во-вторых, каково было бы значение "удаляемого объекта", если оно было передано нулевым указателем? В конце концов, там нет "объекта".
Хорошо, рассмотрим, что означает интерпретировать этот текст, если "объект, удаляемый", говорит конкретно об объекте в конце этого указателя. Что произойдет, если вы удалите массив неполных классов с нетривиальными деструкторами?
В соответствии с этой логикой этот пункт не применяется, является ли указатель нулевым или нет. Зачем? Поскольку "объект, удаляемый", имеет тип массива, а не тип класса. И поэтому этот пункт не может применяться. Это означает, что компилятор должен иметь возможность вызывать delete[]
в массиве неполных классов.
Но это невозможно реализовать; это потребует, чтобы компилятор мог отслеживать код, который еще не существует.
Таким образом, либо "удаляемый объект" предназначен для обозначения std::remove_pointer_t<std::decay_t<decltype(expr)>>
, либо для стандарта требуется поведение, которое невозможно реализовать. Стандартную формулировку можно было бы немного почистить, заменив "Если удаляемый объект имеет неполный тип класса в точке удаления" с "Если T
является указателем на U
или массивом U
и U
имеет неполный тип класса в точке удаления,..."