5

If an exception is thrown in a object's constructor then will the destructor be called? Or is it undefined behaviour? (Which is why I'm reluctant to say what my compiler does.)

struct foo()
{
    foo(){
        throw "bar";
    }
    ~foo(){
        /*am I called*/
    }
};

foo f;
P45 Imminent
  • 8,319
  • 4
  • 35
  • 78

2 Answers2

4

The destructor will not be called because the foo object is not considered fully constructed until a constructor has finished executing (note that this means if you throw in a constructor that delegated to a different constructor then the destructor will be called). Throwing from a constructor is not undefined behaviour.

Simple
  • 13,992
  • 2
  • 47
  • 47
  • this answer appears to contractict quantdev's – P45 Imminent Jun 12 '14 at 14:10
  • @YogiBear this answer is correct. Luckily this is very easy for you to test yourself. – Simple Jun 12 '14 at 14:12
  • I did test it but I inherit the "undefined behaviour" nervousness from my boss! – P45 Imminent Jun 12 '14 at 14:18
  • @YogiBear: This is a very well-defined behaviour. While quantdev gave the wrong answer, he gave the right link. There is no UB, and no memory leak [if you do it right](http://www.parashift.com/c++-faq-lite/selfcleaning-members.html). (Well, not as the FAQ states, since `auto_ptr` is deprecated in C++11. But any of the other [smart pointers](http://en.cppreference.com/w/cpp/memory) will do fine. If you need to be portable across C++ versions, [boost::shared_ptr](http://www.boost.org/doc/libs/1_55_0/libs/smart_ptr/shared_ptr.htm) will do. – DevSolar Jun 12 '14 at 14:20
  • If you need the destructor to be called to free some resource then you should make the data member holding that resource a smart pointer/some other RAII object. While `~foo` isn't called, the destructor of the data member *will* be called because the data member is fully constructed. – Simple Jun 12 '14 at 14:22
3

The lifetime of an object begins when its constructor finishes its execution. That means, before the end of the constructor execution, the object did never exist. So, there's no live object, and thus, there is no destructor to call.

Consequently, there's no undefined behaviour, unless the creation of the exception object throws another exception. In such a case, the program aborts inmediatly.

However, any other object fully constructed before the exception is destructed appropriately, including base subobjects, other member objects, local objects declared in the same scope of the function throwing the exception, and any other objects of previous scopes which don't catch that exception.

Check it out, stack unwinding (on stackoverflow, google and wikipedia, in that order of preference).

ABu
  • 10,423
  • 6
  • 52
  • 103