如果我这样做
Bat::Bat() : m_member_str(new std::string("Am I freed?"))
{
throw std::runtime_error("oops");
}
new
已分配std::string
已被释放?我想这可能是因为没有调用析构函数。
我没有使用std :: string ,而是我自己的类,只是将它作为一个简单的示例显示。
答案 0 :(得分:3)
此示例是智能指针的经典用例。 Bat
未完全构造,因此不会调用析构函数,但m_member_str
和所有其他完全构造的成员的析构函数将是。如果你不想要一个像try { foo(); } catch (...) { delete m_member_str; }
这样的丑陋块,你必须对RAII感到满意。
std::auto_ptr
或boost::scoped_ptr
将帮助您使用C ++ 03,或者它们在C ++ 11中的等价物。将它们用于拥有的成员指针几乎没有什么缺点。
答案 1 :(得分:3)
完全构造的对象会调用它们的析构函数。 部分构造的对象不会。
在您的情况下,您的Bat
对象是部分构造的,因为您从其构造函数中抛出了异常。因此~Bat()
将不被调用。
m_member_str
但 已完全构造,因此将调用其析构函数 。
但是,我们不可能看到该对象的类型。
如果是std::string*
,则不会发生任何事情。它是一个指针,并且销毁指针不会删除它指向的内存。
如果它是某种形式的智能指针,那么它的析构函数将被调用,它将安全地处理你分配的内存。
通常,只要您的成员是RAII对象并拥有有意义的析构函数,无论如何都会清理它们。
如果不是,就像在这种情况下那样,你必须自己处理后果,可能会抓住异常,释放内存然后重新抛出。
答案 2 :(得分:1)
不,除非你照顾它,否则该物体将被泄露。最好的方法是使用智能指针作为成员变量。一般规则是在堆栈展开期间销毁完全构造的对象,同样适用于m_member_str
变量,但由于它是一个原始指针,析构函数将是微不足道的,不会触及指向的对象。 / p>
答案 3 :(得分:1)
你完全改变了你的问题 - 使我原来的答案无效! ;-P
是否使用new释放了字符串?
没有
我在想它可能只是因为没有调用析构函数
不相关。要获得释放,您基本上需要一个构造对象,其中将调用析构函数 ,并且构造函数在其中执行释放(或者您可以使用try / catch块并显式执行)
那么我怎样才能释放m_member_str,如果它是成员指针?
(首先,最好的一般方法是使成员变量m_member_str
成为字符串而不是指向字符串的指针 - 然后字符串析构函数将清理。)
如果必须有指针,请使用智能指针捕获指针,以便智能指针的析构函数析构指向的对象和释放内存。当异常处理期间失败的构造函数销毁已构造的成员变量时,将调用此方法。