2014-10-28 1 views
2

Почему исключение неполного типа определяется как «неопределенное поведение»?Почему исключение неполного типа определяется как «неопределенное поведение»?

Из спецификации C++; §5.3.5/5;

Если объект удаляются имеет неполный тип класса в точке удаления, а полный класс имеет нетривиальный деструктор или функцию Deallocation, поведение не определенно.

Учитывая пример кода (я понимаю, почему это ошибка);

class ABC; 

int main() 
{ 
    ABC* p = nullptr; 
    delete p; 
} 

Почему определяется как быть определено поведение при НКУ, лязг и MSVC все предупреждают о его будучи неполным типа? Почему не просто ошибка в этой точке, то есть Почему это не диагностическая ошибка?

+0

Возможный дубликат [Почему, действительно, удаление неполного типа является неопределенным поведением?] (Http://stackoverflow.com/questions/2517245/why-really-deleting-an-incomplete-type-is-undefined-behaviour) – CoryKramer

+0

@Cyber. Вот почему это ошибка. Я хочу знать, почему это было определено как «неопределенное поведение» - почему компилятор не обязан отказываться от компиляции? – Niall

+0

Проблема может быть поднята для любого метода в объявленном, но еще неопределенном классе. Однако компилятор знает, что деструктор существует и может иметь определенное определение (тривиальное), в отличие от любого другого произвольного метода. Единственное, что пока не известно, будет ли деструктор виртуальным или нет, что может изменить соглашение о вызове (этот вопрос подкрепляется ответом на другой вопрос). – didierc

ответ

3

Выражение delete p; делает две вещи:

  1. уничтожить весь объект, который содержит *p.
  2. Освободите память, используемую для хранения указанного объекта.

Пункт 2 может быть возможным, когда все, что вы знаете, это адрес объекта, без какой-либо дополнительной информации. Распределитель памяти заботится только об адресах. Но определение адреса полного объекта может быть затруднено; вам по существу нужно обещать, что вы фактически предоставляете адрес полного объекта.

Но есть еще. Прежде чем освобождать память объекта, вы должны запустить деструкторы (пункт 1). Если деструктор не имеет эффекта, тогда допустимо не запускать деструкторы, так как это имеет такое же поведение , как будто вы их запустили. Но если работающие деструкторы действительно имеют эффект, опускание элементов 1 приводит к неопределенному поведению, и вам нужно знать полный тип, чтобы знать, как запускать destrutors. Кстати, вам также нужно знать полный тип, чтобы определить адрес самого производного объекта для пункта 2.

+0

Таким образом, единственная «определенная» -существо здесь будет, если деструктор не имеет никакого эффекта, а затем освобождение памяти - это все, что происходит? – Niall

+0

@Niall: Да, с разъяснением, что уничтожение объекта с помощью полиморфного указателя базы всегда является «эффектом». –

5

Потому что, как говорится в цитате, это только неопределенное поведение, если оно имеет нетривиальный деструктор или функцию освобождения. Если он неполный, компилятор не знает, действительно ли это так, поэтому не знает, хорошо ли определена программа.

+0

Итак, в основном вы говорите, что единственный четко определенный случай будет для типа POD? – Niall

+1

@Niall: Нет. Ваша цитата говорит, что она хорошо определена для любого типа, у которого есть тривиальный деструктор и нет функции освобождения. –

+0

@Niall Обратите внимание, что вполне возможно, чтобы класс имел нетривиальную копию ctor (делая ее не-POD), имея тривиальный dtor. – Angew

Смежные вопросы