2015-03-23 5 views
0

Согласно следующей статье: Why isn’t the destructor called at the end of scope?Удалять объект внутри функции: некрасиво, подверженных ошибкам, неэффективна, и, как правило, не исключение безопасного

код, который создает объект с использованием новых, а затем удаляет его в конце тот же самый охват является уродливым, подверженным ошибкам, неэффективным и обычно небезопасным. Например:

void very_bad_func() // ugly, error-prone, and inefficient 
    { 
     X* p = new X; 
     // use p 
     delete p; // not exception-safe 
    } 

Мой код, который я надеюсь, что не безобразно:

Я создаю объект типа TiXmlDocument и удалить его до конца функции.

void DataLoader::readXmlFile(const string & file) 
{ 
    TiXmlDocument *doc = new TiXmlDocument(file.c_str()); 
    bool loadOkay = doc->LoadFile(); 
    TiXmlHandle hdl(doc); 

    //work is done in here 
    if(loadOkay) 
    { 
     TiXmlElement * pRoot = hdl.FirstChildElement().Element();//.FirstChildElement().Element(); 
     parseFile(pRoot); 
    } 
    else 
    { 
     cout <<"Error: "<< doc->ErrorDesc()<<endl; 
    } 
    //deallocate doc 
    delete doc; 
} 

Вопрос (ы):

  • Должен ли я использовать DataLoader::~DataLoader() {} деструктор для того, чтобы гарантировать, что объект будет удален после того, как я покину сферу функции? без необходимости явно удалять его delete doc.

Как предположил я сделал следующее:

TiXmlDocument doc(xmlFile.c_str()); 
bool loadOkay = doc.LoadFile(); 
TiXmlHandle hdl(&doc); 

Я начинаю думать, что использование динамической памяти так же, как Java и C# не является хорошей практикой (следует использовать в ответственной способ) в C++. Если нет реальной причины использовать его, тогда нет. Если не обрабатывать правильно, это вызовет утечку памяти, которую трудно отследить.


+0

Вы имеете в виду что-то вроде [умных указателей] (http://msdn.microsoft.com/en-us/library/hh279674.aspx)? 'std :: unique_ptr doc (новый файл TiXmlDocument (file.c_str()));' –

ответ

7

Либо создать объект без нового:

void func() 
{ 
    X p; 
    // use p 
} 

Или, если вы должны использовать новый (например, это большой объект), а затем использовать смарт-указатель:

void func() 
{ 
    std::unique_ptr<X> p(new X); 
    // use p 
} 

проблемы решена!

+0

Что я сделал, это следующее, пожалуйста, проверьте вопрос –

+1

@HaniGoc: Не помогите вампиру. Один вопрос за раз. –

+0

@ KerrekSB извините моя ошибка. Я удалю последнюю часть. –

3

Это все еще уродливо (на мой взгляд), и, безусловно, подвержено ошибкам, неэффективно, а не безопасно. Если во время этой функции выбрано исключение, delete не произойдет, и вы будете утечки памяти.

В этом случае нет необходимости в new; используйте автоматическую переменную, которая будет автоматически уничтожена при выходе из функции, будь то путем достижения цели, возврата или метания.

TiXmlDocument doc(file.c_str()); 

Если вы сделали нужно динамическое распределение по какой-то причине, а затем использовать смарт-указатель или другой RAII типа, чтобы получить такое же автоматическое поведение:

auto doc = std::make_unique<TiXmlDocument>(file.c_str());   // C++14 or later 
std::unique_ptr<TiXmlDocument> doc(new TiXmlDocument(file.c_str())); // C++11 

Чтобы ответить на последний вопрос: использовать деструктор освобождать ресурсы, управляемые экземпляром класса, а не временные ресурсы, используемые в вызове функции.Опять же, вы должны обычно использовать типы RAII в качестве переменных-членов для автоматического управления этими ресурсами, так что вам не нужно писать деструктор самостоятельно.

+0

Можете ли вы проверить мой вопрос после его редактирования. –

+0

@HaniGoc: Да, если вы по-прежнему хотите использовать 'new', а не автоматическую переменную по какой-то причине, это выглядит правильно, предполагая, что' TiXmlHandle' не делает что-то глупое, как удалить указатель, который он задал. –

+0

Я не знаю, что будет 'TiXmlHandle', это проблема. Так что я думаю, что лучше, как вы сказали, использовать смарт-указатели правильно? –