在 C++ 中,什么时候最好使用堆栈(stack)?什么时候最好使用堆(heap)?
在 C++ 中,什么时候最好使用堆栈(stack)?什么时候最好使用堆(heap)?
如果变量在当前函数返回后不再使用,请使用栈。如果变量中的数据需要超出当前函数的生命周期,则使用堆。
一般情况下,避免在堆栈上创建过大的对象。
当你使用的内存严格限制在你创建它的范围内时,使用堆栈是很有用的。这样可以避免内存泄漏,因为你知道在哪里使用内存,也知道何时不再需要它,所以内存会被自动清理。
int main()
{
if (...)
{
int i = 0;
}
// I know that i is no longer needed here, so declaring i in the above block
// limits the scope appropriately
}
然而,堆在内存可能会在其创建范围之外被访问且不希望复制栈变量时非常有用。这可以让您明确控制内存的分配和释放。
Object* CreateObject();
int main()
{
Object* obj = CreateObject();
// I can continue to manipulate object and I decide when I'm done with it
// ..
// I'm done
delete obj;
// .. keep going if you wish
return 0;
}
Object* CreateObject()
{
Object* returnValue = new Object();
// ... do a bunch of stuff to returnValue
return returnValue;
// Note the object created via new here doesn't go away, its passed back using
// a pointer
}
int main()
{
boost::shared_ptr<Object> obj = CreateObject();
// I can continue to manipulate object and I decide when I'm done with it
// ..
// I'm done, manually delete
obj.reset(NULL);
// .. keep going if you wish
// here, if you forget to delete obj, the shared_ptr's destructor will note
// that if no other shared_ptr's point to this memory
// it will automatically get deleted.
return 0;
}
boost::shared_ptr<Object> CreateObject()
{
boost::shared_ptr<Object> returnValue(new Object());
// ... do a bunch of stuff to returnValue
return returnValue;
// Note the object created via new here doesn't go away, its passed back to
// the receiving shared_ptr, shared_ptr knows that another reference exists
// to this memory, so it shouldn't delete the memory
}
一般来说,尽可能使用堆栈。例如,在该变量在该范围之外不需要时。
这样更快,引起的碎片也较少,并且可以避免与调用malloc或new相关的其他开销。从堆栈分配只需要几个汇编操作,而malloc或new则需要在高效实现中数百行代码。
虽然无法避免,但从未最好使用堆... :)
以上提到的规则有一个例外,即通常应该使用堆栈存储本地变量,这些变量在函数范围之外不需要使用:
如果递归函数分配了大量本地变量或被多次递归调用,可能会耗尽堆栈空间。如果您有一个利用内存的递归函数,使用基于堆的内存而不是基于堆栈的内存可能是一个好主意。
在运行时仅使用堆来分配对象空间。如果您在编译时知道大小,请使用堆栈。不要从函数返回堆分配的对象,而是将缓冲区传递到函数中以进行写入。这样,缓冲区可以在调用函数的位置作为数组或其他基于堆栈的结构进行分配。
您拥有的malloc()语句越少,内存泄漏的机会就越少。
有些情况下你需要使用栈,有些情况下你需要使用堆,有些情况下你需要使用静态存储,有些情况下你需要使用常量内存数据,有些情况下你需要使用自由存储。
栈很快,因为分配只是在SP上的“增量”,并且所有的“分配”都是在函数调用时执行的。堆(或自由存储)的分配/释放更加耗时且容易出错。