我的c ++代码中有关于内存管理的一般问题。当我用指向我已在堆栈上动态初始化的对象的新指针替换指向对象的指针时,编译器抱怨存在潜在的内存泄漏。例如:
int* foo(int* h){
int* b = new int(5);
b = h; //Memory leak here. How do I delete b without creating a dangling pointer?
return b;
}
然后我使用此函数来更改指针的状态
int i = 1;
int* c = &i;
foo(c);
所以我的问题是我有一个类具有与上面类似的功能。 我什么时候可以从foo函数中删除b?
delete b;
这会进入析构函数(这对我没有帮助,因为我使用函数foo加载了很多次。所以堆可能会用完......?)
如果我上面没有提供足够的信息。请告诉我。
答案 0 :(得分:3)
如果你真的想用函数中分配的新指针替换指针的值,我建议使用引用:
void SomeClass::foo(int*& h)
{
delete h;
h = new int(5);
}
当然,如果你使用指向堆上不的int
的指针调用它会中断,因为你不能delete
案件。所以不要这样做。
答案 1 :(得分:2)
由于这是一般性问题,我首选的一般方法是使用在您的班级中使用RAII处理的智能指针。
智能指针封装了原始指针,并为您处理所需的内存管理 - 当您的类被破坏时,当时保存的任何指针值都将被清除而无需您手动删除它。为智能指针指定新值时,它会自动删除现有值(如果有)。
boost::scoped_ptr作为班级成员应该在这里为你效力。
这里似乎也存在混淆,关于堆栈上的内容以及堆上的内容。你不会仅仅因为你一遍又一遍地调用foo
而耗尽堆栈(除非你无限制地进入foo
,在这种情况下你将最终耗尽堆栈空间)。您的本地变量b
位于堆栈中,但它指向使用堆上的new
分配的内存。当您退出foo
时,将为调用函数重置堆栈 - 用于b
的堆栈内存现在可用于它调用的下一个函数 - 但您仍需要保留所有权(并最终释放) b
指向的堆内存。
编辑:一些示例代码应该澄清智能指针方法
class MyClass {
public:
MyClass() {} // no explicit init for myPointer needed
~MyClass() {} // frees up any pointer held in myPointer, no explicit delete needed
void Foo(int* c)
{
myPointer.reset(c); // releases any existing value, takes ownership of c
}
private:
boost::scoped_ptr<int> myPointer; // initially empty
};