Подтвердить что ты не робот

Удаление объектов неполного типа

Это заставило меня подумать:

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?

4b9b3361

Ответ 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. Насколько мне известно, просто нет такой вещи, как предупреждение о том, что компилятор должен испускать. Предупреждения являются выборными; они там, потому что автор компилятора подумал, что они будут полезны.