Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

throwing exception from constructor in C++

I have read several articles here and else where that it is OK to throw exception from constructor. However, I have noticed that it doesn't call destructor of base class or its data members if an exception is thrown from the constructor. Consider the following example:

#include <iostream>
using namespace std;
struct C
{
    C() { cout << __FUNCTION__ << endl;  }
    ~C() { cout << __FUNCTION__ << endl; }
};

struct E: public C
{
    C c;
    E() { cout << __FUNCTION__ << endl; throw 4; }
    ~E() { cout << __FUNCTION__ << endl; }
};

int main()
{
    E e;
}


$ g++ test.cpp; ./a.exe
C
C
E
terminate called after throwing an instance of 'int'
Aborted (core dumped)

In this case, E's constructor throws an exception but C's destructor as a data member or as a base class is not called. Now if C's destructor performs some cleanup operation like closing files/sockets and deleting heap allocations, this can cause problems.

So my question is why and when is it OK to throw exceptions from constructors.

like image 988
user236215 Avatar asked Mar 10 '12 01:03

user236215


2 Answers

If you catch the error, the destructor will be run. When an uncaught exception is thrown in C++, the runtime calls std::terminate. By default, std::terminate calls std::abort which specifically does not call destructors on the way out.

With this version:

#include <iostream>
using namespace std;
struct C
{
    C() { cout << __FUNCTION__ << endl;  }
    ~C() { cout << __FUNCTION__ << endl; }
};

struct E: public C
{
    C c;
    E() { cout << __FUNCTION__ << endl; throw 4; }
    ~E() { cout << __FUNCTION__ << endl; }
};

int main()
{
    try {
        E e;
    } catch(...) {
    }

    return 0;
}

I get output:

C
C
E
~C
~C
like image 147
Collin Avatar answered Oct 09 '22 14:10

Collin


I have noticed that it doesn't call destructor of base class or its data members if an exception is thrown from the constructor

Yes, it does.

However, since you don't catch that exception in the entire program, the program is immediately terminated.

If you were to catch the exception somewhere higher up the call stack, then the destructors of base class and members would be invoked as expected.

like image 45
Lightness Races in Orbit Avatar answered Oct 09 '22 13:10

Lightness Races in Orbit