什么时候最好使用栈而不是堆,反之亦然?

在C ++中,何时最好使用堆栈? 什么时候最好使用堆?

在当前函数返回后,当variables不被使用时使用堆栈。 当variables中的数据超出当前函数的使用期限时,使用堆。

根据经验,避免在堆栈上创build巨大的对象。

  • 在堆栈上创build一个对象可以让你免除清理(读取删除)对象的负担。 但是在堆栈上创build太多对象会增加堆栈溢出的可能性。
  • 如果你使用堆对象,你会得到尽可能多的操作系统可以提供的内存,比堆栈大得多,但是当你完成后,你必须确保释放内存。 另外,在堆中过多地创build太多对象往往会使内存碎片化,进而影响应用程序的性能。

当正在使用的内存严格限制在您创build它的范围时使用堆栈。 这对于避免内存泄漏非常有用,因为您确切知道您要使用内存的位置,并且知道何时不再需要内存,因此内存将被清除。

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 } 

但是,如果您的内存可能在创build范围之外访问,并且您不希望复制堆栈variables,那么堆是非常有用的。 这可以给你明确的控制内存如何分配和释放。

 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 } 

显然这里的一个共同的问题是,你可能会忘记删除你的对象。 这被称为内存泄漏。 这些问题比较普遍,因为你的程序变得越来越不重要,因为“所有权”(或者究竟是谁负责删除东西)变得更难以定义。

更多pipe理语言(C#,Java)的通用解决scheme是实现垃圾收集,所以你不必考虑删除东西。 但是,这意味着在后台有一些东西会不定期地检查你的堆数据。 在一个非平凡的程序中,当“垃圾回收”线程popup并突然消失,查找应该删除的数据,而其他程序被阻止执行时,这可能变得相当低效。

在C ++中,处理内存泄漏的最常见和最好的(在我看来)解决scheme是使用智能指针。 其中最常见的是boost :: shared_ptr ,它是( 引用计数 )

所以重新创build上面的例子boost :: shared_ptr CreateObject();

 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 } 

上面提到的规则的一个例外是,您通常应该使用堆栈来存储函数范围之外不需要的局部variables:

如果recursion函数分配大的局部variables或recursion调用多次,recursion函数会耗尽堆栈空间。 如果你有一个利用内存的recursion函数,那么使用基于堆的内存而不是基于堆栈的内存可能是个好主意。

这个问题是相关的(虽然不是真正的愚弄) 什么,堆栈和堆在哪里 ,这是几天前问。

使用堆只在运行时为对象分配空间。 如果你知道编译时的大小,使用堆栈。 不要从函数返回堆分配的对象,而是将缓冲区传递给函数来写入。 这样,缓冲区可以被分配到函数被调用为数组或其他基于堆栈的结构中。

您拥有的malloc()语句越less,内存泄漏的机会就越less。

根据经验,尽可能使用堆栈。 即在该范围之外从不需要variables的时候。

它更快,导致更less的碎片,并将避免与调用malloc或新的相关的其他开销。 分配堆栈是几个汇编操作,malloc或new是有效实现中的几百行代码。

它从来没有最好的使用堆…只是不可避免的。 🙂

这个问题是不健康的。

有些情况下需要堆栈,其他需要堆的地方,其他需要静态存储的地方,其他需要常量内存数据的地方以及需要免费存储的地方。

堆栈速度很快,因为分配只是SP上的一个“增量”,所有的“分配”都是在你所在函数的调用时执行的。堆(或自由存储)分配/释放更为耗时且容易出错。