如果我在对象的构造函数中使用new分配内存并且在抛出异常后立即泄漏?
根本不应该构造对象,因此不会调用析构函数,但那个内存会怎么样?
e.g。
MyObject() {
data = new char[200]; // Will this be leaked?
if(something_is_wrong)
throw exception();
}
答案 0 :(得分:4)
它会泄漏。从new
获得指针后,最终需要delete
d。解决方案是使data
成为智能指针(或者在这种情况下,可能是std::string
);虽然MyObject
的析构函数无法被调用,但数据成员'析构函数被调用。
答案 1 :(得分:2)
是的,除非data
是句柄,智能指针而不是原始指针char* data
,否则它将是泄漏。一个安全的变体是:
class MyObject {
std::vector<char> data; // or some handle/smart pointer (i.e. unique_ptr)
// it might be just std::string
public:
MyObject( int sz) : data( sz) {}
};
在这种情况下,使用的内存现在由vector管理。您当然可以自己完成实际在向量中完成的操作,并且异常安全。这是您可以使用类似于std::uninitialized_fill
的方法。
答案 2 :(得分:1)
除非data
是智能指针(或者更常见的是,任何在解析时释放传递给它的内存的对象),否则会泄漏内存。
new
需要与delete[]
平衡(请注意[]
)。需要注意的是,由于未创建MyObject
实例,因此MyObject
的析构函数将不,因此您无法依赖任何内存清理。
两种选择。
throw
声明之前释放内存。data
成为智能指针(如果尚未指定)。2是首选 - 通过利用RAII,它使代码更稳定。
答案 3 :(得分:1)
你勾画的情况,
MyObject() {
data = new char[200]; // Will this be leaked?
if(something_is_wrong)
throw exception();
}
将 1 泄漏,除非使用自动垃圾收集(即便如此,它仍可能泄漏)。
使用适当的标准库容器可以很容易地处理这种情况:
MyObject()
{
string data( 200, '\0' );
if(something_is_wrong)
throw exception();
}
通常优先使用标准库容器而不是所有这些新容器,如果没有合适的容器,请使用智能指针,例如std::unique_ptr
。
简而言之,没有真正的问题,只不过是对std::terminate
的调用是一个问题(只是删除了电话,或者首先不要这样做)。
但是,如果为类定义自定义分配函数,并忘记定义相应的释放函数,则从构造函数中抛出异常可能会泄漏内存。
作为学习者,根本不定义分配函数。
作为一名专业人士,如果在某个时候你确实需要它,请记得正确地做到这一点。
<小时/> 1)在合理的假设下,你没有使用智能指针来保证清理和在不提及智能指针的情况下提出这个问题。 < p>