C++ 什么时候最好使用堆栈而不是堆,反之亦然?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/102009/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
When is it best to use the stack instead of the heap and vice versa?
提问by Anthony Glyadchenko
In C++, when is it best to use the stack? When is it best to use the heap?
在 C++ 中,什么时候最好使用堆栈?什么时候使用堆最好?
采纳答案by Eddie Deyo
Use the stack when your variable will not be used after the current function returns. Use the heap when the data in the variable is needed beyond the lifetime of the current function.
当您的变量在当前函数返回后不会被使用时,请使用堆栈。当需要变量中的数据超出当前函数的生命周期时,使用堆。
回答by nullDev
As a rule of thumb, avoid creating huge objects on the stack.
根据经验,避免在堆栈上创建巨大的对象。
- Creating an object on the stack frees you from the burden of remembering to cleanup(read delete) the object. But creating too many objects on the stack will increase the chances of stack overflow.
- If you use heap for the object, you get the as much memory the OS can provide, much larger than the stack, but then again you must make sure to free the memory when you are done. Also, creating too many objects too frequently in the heap will tend to fragment the memory, which in turn will affect the performance of your application.
- 在堆栈上创建一个对象可以使您免于记住清理(读取删除)对象的负担。但是在堆栈上创建太多对象会增加堆栈溢出的机会。
- 如果您为对象使用堆,您将获得操作系统可以提供的尽可能多的内存,比堆栈大得多,但是您必须再次确保在完成后释放内存。此外,在堆中过于频繁地创建过多对象会导致内存碎片化,进而影响应用程序的性能。
回答by Doug T.
Use the stack when the memory being used is strictly limited to the scope in which you are creating it. This is useful to avoid memory leaks because you know exactly where you want to use the memory, and you know when you no longer need it, so the memory will be cleaned up for you.
当正在使用的内存严格限制在您创建它的范围内时,请使用堆栈。这对于避免内存泄漏很有用,因为您确切地知道要在何处使用内存,并且知道何时不再需要它,因此将为您清理内存。
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
}
The heap, however, is useful when your memory may be accessed outside of the scope of its creation and you do not wish to copy a stack variable. This can give you explicit control over how memory is allocated and deallocated.
但是,当您的内存可能在其创建范围之外被访问并且您不希望复制堆栈变量时,堆非常有用。这可以让您明确控制如何分配和释放内存。
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
}
Obviously a common problem here is that you may forget to delete your object. This is called a memory leak. These problems are more prevalent as your program becomes less and less trivial where "ownership" (or who exactly is responsible for deleting things) becomes more difficult to define.
显然,这里的一个常见问题是您可能忘记删除您的对象。这称为内存泄漏。随着您的程序变得越来越不重要,其中“所有权”(或谁负责删除内容)变得越来越难以定义,这些问题变得更加普遍。
Common solutions in more managed languages (C#, Java) are to implement garbage collection so you don't have to think about deleting things. However, this means there's something in the background that runs aperiodically to check on your heap data. In a non-trivial program, this can become rather inefficient as a "garbage collection" thread pops up and chugs away, looking for data that should be deleted, while the rest of your program is blocked from executing.
更多托管语言(C#、Java)中的常见解决方案是实现垃圾收集,因此您不必考虑删除内容。但是,这意味着后台有一些东西会不定期运行以检查您的堆数据。在一个非平凡的程序中,这可能会变得相当低效,因为“垃圾收集”线程会弹出并匆匆离开,寻找应该删除的数据,而程序的其余部分则被阻止执行。
In C++, the most common, and best (in my opinion) solution to dealing with memory leaks is to use a smart pointer. The most common of these is boost::shared_ptrwhich is (reference counted)
在 C++ 中,处理内存泄漏的最常见和最好(在我看来)的解决方案是使用智能指针。其中最常见的是boost::shared_ptr,它是(引用计数)
So to recreate the example above boost::shared_ptr CreateObject();
所以要重新创建上面的例子 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
}
回答by Kluge
An exception to the rule mentioned above that you should generally use the stack for local variables that are not needed outside the scope of the function:
上面提到的规则的一个例外是,您通常应该将堆栈用于函数范围之外不需要的局部变量:
Recursive functions can exhaust the stack space if they allocate large local variables or if they are recursively invoked many times. If you have a recursive function that utilizes memory, it might be a good idea to use heap-based memory instead of stack-based memory.
如果递归函数分配大的局部变量或递归调用多次,它们可能会耗尽堆栈空间。如果您有一个使用内存的递归函数,那么使用基于堆的内存而不是基于堆栈的内存可能是个好主意。
回答by jheriko
as a rule of thumb use the stack whenever you can. i.e. when the variable is never needed outside of that scope.
根据经验,只要有可能就使用堆栈。即在该范围之外永远不需要变量时。
its faster, causes less fragmentation and is going to avoid the other overheads associated with calling malloc or new. allocating off of the stack is a couple of assembler operations, malloc or new is several hundred lines of code in an efficient implementation.
它更快,导致更少的碎片,并且将避免与调用 malloc 或 new 相关的其他开销。从堆栈中分配是几个汇编操作,malloc 或 new 是有效实现中的数百行代码。
its never best to use the heap... just unavoidable. :)
使用堆从来都不是最好的......只是不可避免的。:)
回答by pkaeding
This question is related (though not really a dupe) to What and where are the stack and heap, which was asked a couple days ago.
这个问题与几天前问过的What 以及 stack 和 heap 在哪里有关(虽然不是真正的骗局)。
回答by Kyle Cronin
Use the heap for only allocating space for objects at runtime. If you know the size at compile time, use the stack. Instead of returning heap-allocated objects from a function, pass a buffer into the function for it to write to. That way the buffer can be allocated where the function is called as an array or other stack-based structure.
使用堆仅在运行时为对象分配空间。如果您在编译时知道大小,请使用堆栈。不是从函数返回堆分配的对象,而是将缓冲区传递给函数以供其写入。这样可以在函数被调用的地方分配缓冲区作为数组或其他基于堆栈的结构。
The fewer malloc() statements you have, the fewer chances for memory leaks.
您拥有的 malloc() 语句越少,内存泄漏的机会就越少。
回答by ugasoft
The question is ill formed.
这个问题格式不正确。
There are situations where you need the stack, others where you need the heap, others where you need the static storage, others where you need the const memory data, others where you need the free store.
在某些情况下,您需要堆栈、需要堆、需要静态存储、需要常量内存数据、需要空闲存储的情况。
The stack is fast, because allocation is just an "increment" over the SP, and all "allocation" is performed at invocation time of the function you are in. Heap (or free store) allocation/deallocation is more time expensive and error prone.
堆栈很快,因为分配只是对 SP 的“增量”,并且所有“分配”都在您所在函数的调用时执行。堆(或自由存储)分配/释放更耗时且容易出错.