11 Nisan 2019 Perşembe

Constructor İçinde Exception Fırlatmak

Giriş
Eğer bir nesnenin costructor metodu içinde exception atılırsa, o nesnenin destructor metodu çağrılmaz. Açıklaması şöyle.
C++11 15.2 Constructors and destructors (2)
An object of any storage duration whose initialization or destruction is terminated by an exception will have destructors executed for all of its fully constructed subobjects (excluding the variant members of a union-like class), that is, for subobjects for which the principal constructor (12.6.2) has completed execution and the destructor has not yet begun execution.
1. Destructor'ımın Çağrılmaması
Örnek
Elimizde şöyle bir kod olsun. Holder sınıfı ve bu sınıfın içinde yaşayan başka bir sınıf var.
class Object
{
public:
  Object() { std::cout << "Object() ctor" << std::endl; }
  ~Object() { std::cout << "~Object() dtor" << std::endl; }
};

class Holder
{

public:
  Holder() :myObjectP( new Object() )
  {
    throw std::exception();
  }
  ~Holder()
  {
    std::cout << "~Holder()" << std::endl;
    delete myObjectP;
  }
private:
  Object* myObjectP;

};
Bu sınıfı kullanmak için şöyle yaparız.
int main(int argc, char* argv[])
{
  try
  {
    std::cout << "begin try" << std::endl;
    Holder h;
  }
  catch ( ... )
  {
    std::cout << "begin catch" << std::endl;
  }
  return 0;
}
Holder nesnesi constructor metodu içinde exception attığı için destructor metodu çağrılmıyor. Dolayısıyla içindeki pointer Object nesnesi de silinmiyor. Çıktı olarak şunu alırız.
begin try
Object() ctor
begin catch
2. New Kullanırken Constructor İçinden Exception Fırlatmak
new memory leak'e sebep olmaz. Açıklaması şöyle.
Whenever the constructor of MyClass throws, new MyClass(); does not produce any memory leak since the storage allocated for MyClass is automatically freed by new when an exception is thrown.
Açıklaması şöyle.
If the new-expression creates an object or an array of objects of class type, access and ambiguity control are done for the allocation function, the deallocation function, and the constructor. If the new-expression creates an array of objects of class type, the destructor is potentially invoked.
Açıklaması şöyle.
If construction of any object in the buffer throws an exception, the previously constructed objects must be destructed. That requires an available destructor.
Örnek
Elimizde şöyle bir kod olsun. Bu kod memory leak'e sebep olmaz.
MyClass* MyClass::getNewMyClassInstance()
{
    return new MyClass();
}
Örnek
Elimizde şöyle bir kod olsun.
int counter;

class Destruct
{
public:
  Destruct()
  {
    if (counter++ > 5)
      throw counter;
  }

  ~Destruct()
  {
    std::cout << "Dtor called\n";
  }
};

int main()
{
  try
  {
    new Destruct[10];
  }
  catch (...){}
}
Çıktı şunu alırız. Burada 7 nesne yaratılıken exception fırlatılıyor. Fully constucted 6 nesne için destructor çağrılıyor.
Dtor called
Dtor called
Dtor called
Dtor called
Dtor called
Dtor called

Hiç yorum yok:

Yorum Gönder