Преамбула: у Херба Саттера есть отличная статья на эту тему:
http://herbsutter.wordpress.com/2008/07/25/constructor-exceptions-in-c-c-and-java/
C ++: да и нет
Хотя деструктор объекта не будет вызван, если его конструктор сгенерирует (объект «никогда не существовал»), деструкторы его внутренних объектов могут быть вызваны.
В качестве резюме, все внутренние части объекта (то есть объекты-члены) будут иметь свои деструкторы, вызываемые в обратном порядке их построения. У каждой вещи, встроенной в конструктор, не будет вызываться деструктор, если RAII не используется каким-либо образом.
Например:
struct Class
{
Class() ;
~Class() ;
Thing * m_pThing ;
Object m_aObject ;
Gizmo * m_pGizmo ;
Data m_aData ;
}
Class::Class()
{
this->m_pThing = new Thing() ;
this->m_pGizmo = new Gizmo() ;
}
Порядок создания будет:
- Конструктор m_aObject будет называться.
- m_aData будет иметь свой конструктор с именем.
- Конструктор класса называется
- Внутри конструктора класса m_pThing будет иметь свой новый, а затем вызываемый конструктор.
- Внутри конструктора класса m_pGizmo будет иметь свой новый и затем вызываемый конструктор.
Допустим, мы используем следующий код:
Class pClass = new Class() ;
Некоторые возможные случаи:
Если m_aData сгенерирует конструкцию, то у m_aObject будет вызван деструктор. Затем память, выделенная «новым классом», освобождается.
Если m_pThing выбросит новое Thing (из памяти), m_aData, а затем m_aObject вызовут свои деструкторы. Затем память, выделенная новым классом, освобождается.
Если m_pThing сгенерирует конструкцию, память, выделенная "новой вещью", будет освобождена. Затем m_aData, а затем m_aObject будут вызывать свои деструкторы. Затем память, выделенная новым классом, освобождается.
Если m_pGizmo сгенерирует конструкцию, память, выделенная "new Gizmo", будет освобождена. Затем m_aData, а затем m_aObject будут вызывать свои деструкторы. Затем память, выделенная новым классом, освобождается. Обратите внимание, что утечка m_pThing
Если вы хотите предложить Базовую гарантию исключений, вы не должны просачиваться даже в конструктор. Таким образом, вам придется написать так (используя STL или даже Boost):
struct Class
{
Class() ;
~Class() ;
std::auto_ptr<Thing> m_pThing ;
Object m_aObject ;
std::auto_ptr<Gizmo> m_pGizmo ;
Data m_aData ;
}
Class::Class()
: m_pThing(new Thing())
, m_pGizmo(new Gizmo())
{
}
Или даже:
Class::Class()
{
this->m_pThing.reset(new Thing()) ;
this->m_pGizmo.reset(new Gizmo()) ;
}
если вы хотите / должны создать эти объекты внутри конструктора.
Таким образом, независимо от того, куда бросает конструктор, ничто не будет пропущено.