简体   繁体   English

new然后抛出C ++构造函数?

[英]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? 是否释放了new分配的std::string 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. 我没有使用std :: string ,而是使用我自己的类,只是将它显示为一个简单的例子。

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. Bat没有完全构造,因此不会调用析构函数,但是m_member_str和所有其他完全构造的成员的析构函数将是。 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; } try { foo(); } catch (...) { delete m_member_str; } , you'll have to get comfortable with RAII. try { foo(); } catch (...) { delete m_member_str; } ,你必须得舒服RAII。

std::auto_ptr or boost::scoped_ptr will help you in C++03, or their equivalents in C++11. std::auto_ptrboost::scoped_ptr将帮助您使用C ++ 03,或者它们在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. 在您的情况下,您的Bat对象是部分构造的,因为您从其构造函数中抛出了异常。 So ~Bat() will not be called. 所以~Bat() 不会被调用。

m_member_str however, is fully constructed, and so its destructor will be called. 但是, m_member_str 完全构造的,因此调用它的析构函数。 However, it is impossible for us to see the type of that object. 但是,我们不可能看到该对象的类型。

If it is a std::string* then nothing will happen. 如果是std::string*则不会发生任何事情。 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. 一般来说,只要你的成员是RAII对象并拥有一个有意义的析构函数,无论如何都会清理它们。

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. 一般规则是在堆栈展开期间销毁完全构造的对象,同样适用于m_member_str变量,但由于它是原始指针,因此析构函数将是微不足道的,并且不会触及指向的对象。

You've completely changed your question - invalidating my original answer! 你完全改变了你的问题 - 使我原来的答案无效! ;-P ;-P

Is the string allocated with the new freed? 是否使用new释放了字符串?

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). 为了获得释放,你基本上需要有其析构函数被称为构造的对象,并在构造函数中进行释放(或者你可以使用try / catch块,做这一切明确)。

so how can I free m_member_str, if it was a member pointer? 那么我怎么能释放m_member_str,如果它是一个成员指针?

(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.) (首先,最好的一般方法是使成员变量m_member_str成为字符串而不是指向字符串的指针 - 然后字符串析构函数将清理。)

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. 这将被调用,因为失败的构造函数在异常处理期间销毁已构造的成员变量。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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