Why is my exception still thrown after being caught?

I have the following code in which a variable is initialized with the result of a function call. This function throws so that I created a try-catch to catch the exception. For some reason, the exception is still displayed on the screen even after the catch clause is executed.

#include <iostream> #include <stdexcept> int f() { throw std::invalid_argument("threw"); return 50; } struct S { S() try : r(f()) { std::cout << "works"; } catch(const std::invalid_argument&) { std::cout << "fails"; } int r; }; int main() { S s; } 

This code prints a "crash" after an exception is thrown:

 terminate called after throwing an instance of 'std::invalid_argument' what(): threw 

Why is the exception still throwing? I have the same code that is installed mostly, and it works without crashing:

 int main() { try { throw std::invalid_argument("blah"); } catch(const std::invalid_argument&) { } } 

So, why does this happen when used in a list of initializers?

+6
source share
2 answers

Constructors with try blocks (for example, what you have for S ) automatically reconstruct all exceptions caught by the catch . Therefore, after catch catches the exception, it raises it. This behavior is different from regular catch handlers that do not. I believe that the rationale is that if the construction of the data element or base class is not performed, the object could not be built. The purpose of the catch handler is to simply perform an additional cleanup before the exception is thrown out.

Hope this helps!

+14
source

From C ++ 11, 15.3 / 15 standard:

The exception that is currently thrown is discarded if the control reaches the end of the handler of the try-block function of the constructor or destructor.

The reasons are explained in the GOTW Jerry links for your question, but in short: imagine, if it had not been repeated, then the following lines after S s; presumably they will try to use s , despite the fact that he never completed the construction, and when s leaves the scope, the constructor will organize a call to the destructor for s - potentially freeing never-initialized pointers, freeing never-executed locks, etc.

In contrast, if you allow the default data item to be initialized, and then assign it from the try / catch block in the constructor body, the state of an object that includes databases and data items can potentially be saved in some coherent state: for you, how It is up to the programmer to decide whether this state will be normal - that is, whether you will use the try / catch block inside the constructor body and have later member functions to handle the potentially constructed default data element.

+2
source

Source: https://habr.com/ru/post/959204/


All Articles