Я только начал использовать библиотеки C ++ Boost. Во многих местах я читал, что при использовании scoped_ptr объект всегда уничтожается даже в случае исключений.
Я попробовал в следующем коде.
#include<boost/scoped_ptr.hpp>
class B
{
public:
B(){ std::cout<< "B constructor call\n"; }
~B(){ std::cout<<"B destructor call\n"; }
};
class A
{
public:
boost::scoped_ptr<B> b;
A():b(new B())
{
throw 1;
}
};
int main()
{
A a; return 0;
}
output:
B constructor call
terminate called after throwing an instance of 'int'
Aborted (core dumped)
Там нет вызова к деструктору B. Но я использовал scoped_ptr, поэтому он должен был вызвать деструктор B или неправильно интерпретировал использование scoped_ptr.
Но если окружить его попыткой catch, то вызывается деструктор B.
try{
A a;
} catch( ... ) {
}
В этом случае деструктор A будет вызываться, так как все локально расположенные объекты в случае исключения в блоке try удаляются из стека, и у меня есть мой указатель, заключенный внутрь, и объект scoped_ptr, поэтому, когда деструктор объекта scoped уничтожает, что в конечном итоге указатель ,
Так что scoped_ptr полезен, потому что нам не нужно явно удалять выделенную память, или я неправильно интерпретировал описание scoped_ptr.
Как я могу вызвать деструктор класса B в случае исключения, используя scoped_ptr
Там нет соответствующего обработчика исключений, поэтому std::terminate
вызывается напрямую, в этом случае стек не разматывается. Положить try
/catch
в main
что ловит int
и вы увидите ваш вызов деструктора, даже если этот обработчик сработает.
C ++ 11 §15.1 / 2:
Когда генерируется исключение, управление передается ближайшему обработчику с соответствующим типом; «Ближайший» означает обработчик, для которого компаунд-заявление или же т е р-инициализатор следуя
try
Ключевое слово было недавно введено потоком управления и еще не завершено.
и §15.3 / 9:
Если соответствующий обработчик не найден, функция
std::terminate()
называется; действительно ли стек разматывается перед этим вызовомstd::terminate()
определяется реализацией.
C ++ уничтожает локальную переменную при разматывании стека (возврат из функции, либо с return
ключевое слово или с исключением), поэтому он должен увидеть один, чтобы уничтожить ваш scoped_ptr
, Но в вашем особом случае исключение произошло в main
так terminate
будет вызвана и уничтожит вашу программу, прежде чем C ++ раскрутит стек.
void test() {throw 1;}
void main() {
string sMain;
test();
}
В приведенном выше примере, sMain
не будет уничтожено, потому что исключение вызывает вызов terminate
:
sMain constructed
exception occurred: main has no where to go, and it has no handler to handle
the exception, so it will call `terminate`, but wait we are still at `main`
so we have no stack unwinding here and sMain will never destroyed!!