Constructors and exceptions

Categories:

Problem

What will the following code print to stdout?

 1#include <iostream>
 2
 3using namespace std;
 4
 5struct A {
 6    A() { cout << __PRETTY_FUNCTION__ << endl; }
 7    virtual ~A() { cout << __PRETTY_FUNCTION__ << endl; }
 8};
 9
10struct C {
11    C() { cout << __PRETTY_FUNCTION__ << endl; }
12    ~C() { cout << __PRETTY_FUNCTION__ << endl; }
13};
14
15struct D {
16    D() { cout << __PRETTY_FUNCTION__ << endl; }
17    ~D() { cout << __PRETTY_FUNCTION__ << endl; }
18};
19
20struct E {
21    E() { cout << __PRETTY_FUNCTION__ << endl; }
22    E(const E&) { cout << __PRETTY_FUNCTION__ << endl; }
23    ~E() { cout << __PRETTY_FUNCTION__ << endl; }
24};
25
26struct B: A {
27    D d;
28
29    B() {
30        try {
31            C c;
32            throw E();
33        } catch (E e) {
34            cout << "catch" << endl;
35        }
36        throw E();
37    }
38
39    ~B() { cout << __PRETTY_FUNCTION__ << endl; }
40};
41
42int main() {
43    try {
44        B b;
45    } catch (const E&) {
46    }
47
48    return 0;
49}

Solution

 1A::A()
 2D::D()
 3C::C()
 4E::E()
 5C::~C()
 6E::E(const E&)
 7catch
 8E::~E()
 9E::~E()
10E::E()
11D::~D()
12virtual A::~A()
13E::~E()

Explanation

  1. try block in main().
  2. Default initialization of local variable b in main().
  3. Default constructor of a base class A::A().
  4. Default initialization of data member B::d.
  5. Default constructor D::D().
  6. Default constructor B::B().
  7. Default initialization of local variable c in B::B().
  8. Default constructor C::C().
  9. Throw exception object E (temporary object with unspecified duration).
  10. Default constructor E::E().
  11. Stack unwinding.
  12. Destructor C::~C() (object with automatic storage duration) at the end of try block.
  13. catch exception object E by value.
  14. Copy initialization of exception object: copy constructor E::E(const E&).
  15. Print catch.
  16. Destructor E::~E() (exception object from step 14) at the end of try-catch clause.
  17. Destructor E::~E() (exception object from step 10) at the end of try-catch clause.
  18. Throw exception object E (temporary object with unspecified duration).
  19. Default constructor E::E().
  20. catch exception object E by constant reference in main().
  21. End of try-catch clause in main().
  22. Destructor D::~D() of data member B::d initialized in step 4.
  23. Virtual destructor A::~A() of base class A initialized in step 3.
  24. Destructor E::~E() (exception object from step 19) at the end of main().