2
#include <iostream>
class A
{
    public:
    A() 
    {   
        std::cout << "A()" << std::endl;
    }   

 virtual  ~A()
    {   
        std::cout << "~A()" << std::endl;
    }   
};

class B:public A
{
    public:
    B() 
    {   
        throw std::exception();
        std::cout << "B()" << std::endl;
    }   

   ~B()
    {   
        std::cout << "~B()" << std::endl;
    }   
};


int main()
{
    try 
    {   
        B b;
    }   
    catch(std::exception & e)  
    {   
    }   
    return 0;
}   

The above code outputs,

A()
~A()

By the time the exception is thrown, B has been created. Then why isn't the destructor of B being called?

bisarch
  • 1,388
  • 15
  • 31
  • 2
    Only the destructors of successfully constructed objects are called. In other words, you're wrong in saying that `B` has been created by the time the exception is thrown. See [this](http://stackoverflow.com/a/10212864/2297365). – huu May 08 '15 at 00:31

2 Answers2

6

The object isn't considered fully constructed until its constructor returns, and, destructor is not called on incomplete objects.

Carlton
  • 4,217
  • 2
  • 24
  • 40
2

Carlton is giving the right answer. This design (i.e. not calling dector on anything not fully constructed) has important consequence. Any C++ class can contain only one resource that is protected with destructor. For example this will not work:

class Ab
{
public:
          char *m_buff1;
          char *m_buff2;

          Ab() { m_buff1 = malloc(100); Xyz(); m_buff2 = malloc(200); }
         ~Ab() { free(m_buff1); free(m_buff2); }
};

In case if exception will happen between 2 allocation attempts - there is no way to know safely what field was initialized and what not. I give here simple example to make the point clear. Please, do not comment that it is possible to initialize the fields with NULL first. If exception will happen between mallocs - the first allocation will be simply leaked because the desctuctor will not be called.

In other words it is better to avoid designs that throw exceptions from constructors. Better think about having simple constructor that just initializes data fields and a separate method that allocates resources, opens connections, etc.

Kirill Kobelev
  • 10,252
  • 6
  • 30
  • 51
  • 1
    "Any C++ class can contain only one resource that is protected with destructor." That's not true. It's just that if you have more than one resource is allocated in the constructor, the constructor must make sure that in case of an exception, all already allocated resources are properly deallocated. The best way to ensure it is to use RAII classes that handle this. — "In other words it is better to avoid designs that throw exceptions from constructors." I disagree. Writing a constructor that correctly releases resources is the same as writing another function that correctly releases resources. – celtschk May 08 '15 at 01:10
  • RAII is the right thing and it is doing exactly what I am speaking about, i.e. it is protecting single (!) resource with a class. You are right, it is possible to use try blocks in constructors to protect resource allocation, but I would discourage from using this. It is too complex and in generally worse than RAII. – Kirill Kobelev May 08 '15 at 01:19
  • You advise against throwing from constructors, with the argument that you couldn't get the resource management right. And that I strongly disagree with. – celtschk May 08 '15 at 18:32
  • I advise against because this would require too big effort and not because this is not possible at all. Code should be reasonably complex. Developers should look for solutions that are brief and easy to understand rather than "do it this way now" and think about bigger picture later. – Kirill Kobelev May 09 '15 at 02:31
  • With RAII it is absolutely not complex, and it is certainly possible. – celtschk May 09 '15 at 08:04