简体   繁体   中英

new then throw in C++ constructor?

If I do

Bat::Bat() : m_member_str(new std::string("Am I freed?"))
{
  throw std::runtime_error("oops");
}

Is the new ly allocated std::string freed? I was thinking it might be because the destructor is not called.

I am not using a std::string , but my own class, just showing it as an easy example.

This example is the classic use case for smart pointers. Bat is not fully constructed, so the destructor won't be called, but the destructor for m_member_str and all other fully constructed members will be. If you don't want an ugly block like try { foo(); } catch (...) { delete m_member_str; } try { foo(); } catch (...) { delete m_member_str; } try { foo(); } catch (...) { delete m_member_str; } , you'll have to get comfortable with RAII.

std::auto_ptr or boost::scoped_ptr will help you in C++03, or their equivalents in C++11. There is very little disadvantage in using them for owned member pointers.

Fully constructed objects have their destructor called. Partially constructed objects do not.

In your case, your Bat object is partially constructed, because you threw an exception from its constructor. So ~Bat() will not be called.

m_member_str however, is fully constructed, and so its destructor will be called. However, it is impossible for us to see the type of that object.

If it is a std::string* then nothing will happen. It is a pointer, and destroying a pointer does not delete the memory it points to.

If it is some form of smart pointer, then its destructor will be called, and it will safely handle the memory you allocated.

In general, as long as your members are RAII objects and have a meaningful destructor, they will get cleaned up no matter what.

If the are not, as in this case, then you have to deal with the consequences yourself, possibly bny catching the exception, freeing the memory and then rethrowing.

No, that object will be leaked unless you take care of it. The best way is to use a smart pointer for the member variable. The general rule is that fully-constructed objects are destroyed during stack unwinding and the same applies to m_member_str variable, but since it is a raw pointer the destructor will be trivial and won't touch the pointed-to object.

You've completely changed your question - invalidating my original answer! ;-P

Is the string allocated with the new freed?

No

I was thinking it might be only because the destructor is not called

Not relevant. To get deallocation, you basically need to have a constructed object for which the destructor will be called, and in which the constructor performs deallocation (or you can use a try/catch block and do it all explicitly).

so how can I free m_member_str, if it was a member pointer?

(Firstly, the best general approach is to make the member variable m_member_str a string rather than a pointer-to-string - then the string destructor will clean up.)

If you must have a pointer, use a smart pointer to capture the pointer such that the smart pointer's destructor destructs the pointed-to object and deallocates the memory. This will be invokes as the failing constructor destroys already-constructed member variables during the exception handling.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM