Удаление объектов неполного типа
Это заставило меня подумать:
class X;
void foo(X* p)
{
delete p;
}
Как мы можем delete p
, если мы даже не знаем, имеет ли X
видимый деструктор? g++ 4.5.1 дает три предупреждения:
warning: possible problem detected in invocation of delete operator:
warning: 'p' has incomplete type
warning: forward declaration of 'struct X'
И затем он говорит:
note: ни деструктор, ни оператор класса не удаляются будут вызываться, даже если они объявлены при определении класса.
Wow... компиляторы, необходимые для диагностики такой ситуации, как g++? Или это поведение undefined?
Ответы
Ответ 1
Из стандартного [expr.delete]:
Если удаляемый объект имеет неполный тип класса в точке удаление, а полный класс имеет нетривиальный деструктор или функция освобождения, поведение undefined.
Итак, это UB, если нет нетривиальных вещей, и это нормально, если нет. Предупреждения не требуются для UB.
Ответ 2
Это поведение undefined.
Однако вы можете сделать проверку компилятора для неполных типов, например boost:
// verify that types are complete for increased safety
template<class T> inline void checked_delete(T * x)
{
// intentionally complex - simplification causes regressions
typedef char type_must_be_complete[ sizeof(T)? 1: -1 ];
(void) sizeof(type_must_be_complete);
delete x;
}
Применение sizeof
к неполному типу должно вызывать ошибку, и я полагаю, что если это передается с некоторым компилятором, тогда массив отрицательного размера вызовет ошибку.
Ответ 3
Это поведение undefined, а также обычная реализация при реализации шаблона pImpl. Насколько мне известно, просто нет такой вещи, как предупреждение о том, что компилятор должен испускать. Предупреждения являются выборными; они там, потому что автор компилятора подумал, что они будут полезны.