Ответ 1
Преамбула: У Травы Саттера есть отличная статья по теме:
http://herbsutter.wordpress.com/2008/07/25/constructor-exceptions-in-c-c-and-java/
С++: Да и Нет
Пока объект-деструктор не будет вызываться, если его конструктор выбрасывает (объект "никогда не существовал" ), можно было бы назвать деструкторы его внутренних объектов.
Как сводка, каждая внутренняя часть объекта (т.е. объекты-члены) будет иметь свои деструкторы, вызываемые в обратном порядке их построения. Каждая вещь, встроенная внутри конструктора, не будет иметь своего деструктора, если 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 throw в новом Thing (из памяти), m_aData, а затем m_aObject будет вызван их деструкторами. Затем освобождается память, выделенная новым классом.
-
Если m_pThing бросается при построении, память, выделяемая "новой вещью", будет освобождена. Затем m_aData, а затем m_aObject вызовет их деструкторы. Затем освобождается память, выделенная новым классом.
-
Если m_pGizmo бросает при построении, память, выделенная "новым Gizmo", будет освобождена. Затем m_aData, а затем m_aObject вызовет их деструкторы. Затем память, выделенная новым классом, освобождается. Обратите внимание, что m_pThing просочился
Если вы хотите предложить гарантию Basic Exception, вы не должны течь, даже в конструкторе. Таким образом, вам придется писать это так (используя 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()) ;
}
если вы хотите/должны создавать эти объекты внутри конструктора.
Таким образом, независимо от того, куда бросает конструктор, ничего не будет пропущено.