Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
101 views
in Technique[技术] by (71.8m points)

Exception in Destructor C++

I am well aware of the fact that one should not throw any exception in destructor.

But as a part of making my grip on this concept,I coded this example :-

#include <iostream>
using namespace std;

class A {
private: 
    int i;

public:
    A()
    {
        i = 10;
    }
    ~A()
    {
        throw 30;
    }
};
int main(){
    try{
        A();
        throw 10;
    }
    catch (int i){
        cout << i << endl;
        cout << "exception caught" << endl;
    }
}

As per my understanding, this program should be terminated by calling std::terminate() as there will be two exceptions at the same time. But, this program is giving the following output:-

30
exception caught

Can anyone please explain me the logic behind this as to why this is not terminating?

question from:https://stackoverflow.com/questions/42976461/exception-in-destructor-c

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

std::terminate will be called if an exception is thrown during stack unwinding. That means that if an exception is called while another exception is being handled, then std::terminate will be called.

In your example, that doesn't happen - A(); will construct and immediately destroy an instance of A. The throw 30 will then be caught correctly.

Changing your code to:

int main(){
    try{
        A a;      // begin `a` lifetime 
        throw 10; // | throw #0           
                  // | end `a` lifetime   
                  // throw #1
    }
    catch(int i){
        cout<<i<<endl;
        cout<<"exception caught"<<endl;
    }
}

will guarantee that std::terminate will be called. In this case, a will be destroyed and will throw while another exception is being handled.

live coliru example


Additional information:


Note that in C++11 and above, your code snippet will call std::terminate and provide you a warning:

main.cpp: In destructor ‘A::~A()’:

main.cpp:16:15: warning: throw will always call terminate() [-Wterminate]

     throw 30;

           ^~

main.cpp:16:15: note: in C++11 destructors default to noexcept

terminate called after throwing an instance of 'int'

bash: line 7: 1505 Aborted (core dumped) ./a.out

As seen in the compiler output, since C++11 destructors are implicitly noexcept(true). If you want to prevent this behavior, you can simply mark them as noexcept(false). Example:

~A() noexcept(false)
{
    throw 30;
}

live example on coliru


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...