假设您有一个简单的类,如下所示:
正如您所见,
另外,如何避免这种情况?一种方法是在对象不再需要时手动调用析构函数,但这看起来很丑陋和不熟悉!此外,如果您不修改析构函数并按照原来的方式操作,则可能会出现“double free”的问题。
另一种方法是通过
class foo{
private:
int* mData;
int mSize;
public:
foo(int size){
mSize = size;
mData = new int [mSize];
}
~foo() {
mSize = 0;
delete [] mData;
}
};
然后在主函数中执行以下操作:
int main () {
static int HUGE = 100000000;
foo a(HUGE);
// do something useful with a
// .
// .
// .
// Now I'm done with a; I do not need it anymore ...
foo b(HUGE);
// do something useful with b
// Ok we are done with b
return 0;
}
正如您所见,
b
之后就不再需要a
了,但它是在堆栈上创建的,因此直到程序结束时析构函数才会被调用。我知道这与使用new
并忘记调用delete
不同,但仍然浪费内存。您认为这算是“内存泄漏”还是糟糕的编程风格?另外,如何避免这种情况?一种方法是在对象不再需要时手动调用析构函数,但这看起来很丑陋和不熟悉!此外,如果您不修改析构函数并按照原来的方式操作,则可能会出现“double free”的问题。
foo::~foo(){
if (mData != NULL){
delete [] mData;
mData = NULL;
mSize = 0;
}
}
另一种方法是通过
foo *pa = new foo(HUGE)
创建堆上的 a
,然后在对象不再需要时调用 delete pa
。这种方法虽然可行,但有可能引入另一个内存泄漏的风险(如果忘记调用 delete pa
)。还有更好的方法来处理不需要的对象吗?
std::vector
所做的就是你的类试图做的,但它确实做得正确... - Jerry Coffin~foo
的第二次调用是未定义的。 - Robᵩa
是自动分配的(“在堆栈上”)。这意味着编译器将在作用域结束时无论你喜欢与否都会调用析构函数。但是,如果您已经手动调用了它,则作用域结束时的调用将导致析构函数被调用两次,这是未定义行为。 - GManNickG