Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Destructor not called when an exception is thrown

Tags:

c++

algorithm

Consider the following code:

#include <iostream>
using namespace std;

class Test {
  static int count;
  int id;
public:
  Test() {
    count++;
    id = count;
    cout << "Constructing object number " << id << endl;
    if(id == 4)
       throw 4;
  }
  ~Test() { cout << "Destructing object number " << id << endl; }
};

int Test::count = 0;

int main() {
  try {
    Test array[5];
  } catch(int i) {
    cout << "Caught " << i << endl;
  }
}

The code above produces the following output:

Constructing object number 1
Constructing object number 2
Constructing object number 3
Constructing object number 4
Destructing object number 3
Destructing object number 2
Destructing object number 1
Caught 4

I thought destructors were always called when objects become out of scope, even when exceptions are thrown. Why isn't one of the Test instances' destructors called in this case?

like image 680
Utkarsh Srivastav Avatar asked Jan 28 '12 06:01

Utkarsh Srivastav


2 Answers

You are creating an array of 5 Test objects but you throw an exception after you create 3 complete objects, The exception is thrown while in the constructor of the 4th object. The construction of the 4th object is not complete until the closing brace of the constructor is reached.

The stack unwinds calling destructor for those 3 completely constructed objects in the opposite order in which they were created, since the 4th and 5th object were never constructed the destructor for them is never called.

The rule for exception is:
Once an exception is thrown destructors for all completely created objects within that scope will be called.
An completely created object is one whose constructor has been called cleanly without any exceptions.

like image 146
Alok Save Avatar answered Nov 09 '22 17:11

Alok Save


Instead of writting the cout statement after id=count as mentioned below:-

    id = count;
    cout << "Constructing object number " << id << endl;
    if(id == 4)
    throw 4;

you should have written it after the throw statement . That would have given you a better picture of what happened . Like this :-

Test() {
count++;
id = count;
if(id == 4)
   throw 4;
 cout << "Constructing object number " << id << endl;
     }

The o/p would have been :- Constructing object number 1 Constructing object number 2 Constructing object number 3 Destructing object number 3 Destructing object number 2 Destructing object number 1 Caught 4

like image 40
Invictus Avatar answered Nov 09 '22 16:11

Invictus