1

Указывает ли код ниже утечки памяти?Выбрасывание исключения в конструкторе класса C++

Деструктор класса Test не вызывается (на экране не появляется вывод), и я предполагаю, что вся память, выделенная массиву Int, не возвращается системе? Правильно ли мое предположение? Как мне требовать вернуть ресурсы, выделенные в конструкторе, если возникает исключение?

#include <iostream> 
using namespace std; 

class Int{ 
    public: 
     int v; 
     Int(){ 
     cout<<"inside Int constructor ..."<<endl; 
     } 

     ~Int(){ 
     cout<<"inside Int destructor ..."<<endl; 
     } 
}; 

class Test{ 
    public: 
    Int* a; 

    Test(){ 
     a=new Int[10]; 
     cout<<"inside Test constructor ..."<<endl; 
     throw(0); 
    } 

    ~Test(){ 
     delete [] a; 
     cout<<"inside Test destructor ..."<<endl; 
    } 
}; 

int main(){ 
    try{ 
     Test T; 
    } 
    catch (int e){ 
     cout<<"Error!!!"<<endl; 
    } 

    return 0; 
}  

ответ

1

Деструктор не вызывается, потому что объект никогда не был полностью сконструирован. Вызов его на частично обработанном объекте может быть более опасным, так как он попытается отменить то, что никогда не делалось. Для вас, как программиста, важно, чтобы в случае исключения из конструктора утечки памяти (или какого-либо другого ресурса) не возникало.

Но будут называться деструкторы базовых классов и переменных-членов! Поэтому в большинстве случаев предпочтительнее полагаться на интеллектуальные указатели или контейнеры, которые будут обрабатывать ресурсы для вас. Попытайтесь изменить ваш класс следующим образом:

#include <memory> 

class Test{ 
    public: 
    std::unique_ptr<Int[]> a; 

    Test(){ 
     a=std::make_unique<Int[]>(10); 
     cout<<"inside Test constructor ..."<<endl; 
     throw(0); 
    } 

    ~Test(){ 
     //no need to delete[] a; 
     cout<<"inside Test destructor ..."<<endl; 
    } 
}; 

Это беспроигрышная ситуация. Вы увидите, что будут вызваны деструкторы Int, и вам не нужно вручную обрабатывать память.

0

Я придумал решение, но не уверен, что это хороший дизайн или правильный способ сделать это. вы могли бы прокомментировать?

#include <iostream> 
using namespace std; 

class Int{ 
    public: 
    int v; 
    Int(){ 
     cout<<"inside Int constructor ..."<<endl; 
    } 

     ~Int(){ 
     cout<<"inside Int destructor ..."<<endl; 
    } 
}; 

class Test{ 
    public: 
    Int* a; 

    Test(){ 
     try{ 
      a=new Int[10]; 
      cout<<"inside Test constructor ..."<<endl; 
      throw(0); // exception is thrown 
      } 

     catch (int e){ 
       delete [] a; 
       cout<<"Error!!!"<<endl; 
      } 
     } 

    ~Test(){ 
     delete [] a; 
     cout<<"inside Test destructor ..."<<endl; 
    } 
}; 

int main(){ 

     Test T; 


     return 0; 
}  
Смежные вопросы