85

In C++, when is it best to use the stack? When is it best to use the heap?

Sebastian Paaske Tørholm
  • 49,493
  • 11
  • 100
  • 118
Anthony Glyadchenko
  • 3,572
  • 7
  • 48
  • 66
  • 13
    I assume you mean the system stack and system heap for allocating memory, not the data structures heap and stack, correct? – Doug T. Sep 19 '08 at 15:06
  • Related question: [What and where are the stack and heap?](https://stackoverflow.com/questions/79923/what-and-where-are-the-stack-and-heap) – m7913d Dec 09 '22 at 13:54

7 Answers7

82

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.

Eddie Deyo
  • 5,200
  • 8
  • 35
  • 35
  • 7
    There are ways to get around that though. Passing a buffer to a function that then writes data to it is a good way of having a function "return" dynamic data that lives on in a lower stack frame. It's less OO-like, but it's much more efficient. – Kyle Cronin Sep 19 '08 at 14:10
  • 9
    Size is also a consideration: anything over 1K on the stack should be considered carefully. Sometimes it's better to have a stack pointer to heap memory (together with 'Resource Acquisition is Initialization' idiom) –  Sep 19 '08 at 14:40
  • 3
    But what about when memory is a property of a class, how do you decide when a class property should be a pointer or otherwise? Also when might you use a smart pointer? – JagWire Oct 30 '15 at 16:16
  • 1
    Comming to this question in 2020, I want to point out that this is no longer good practice: Since move and copy elision semantics, passing local variables to the caller can almost always be done efficiently. This also removes the headaches of delete which comes with anything manually managed in the heap. – Rasmus Damgaard Nielsen May 23 '20 at 09:28
41

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.
nullDev
  • 11,170
  • 8
  • 34
  • 52
  • 1
    Since this is still a highly voted question that can be found in 2020, note that many containers which are allocated on the stace (like std::vector) actually allocate their backing storage in the heap. Therefore this is only a concern if you actually has a class with hundreds of properties (which you probably shouldn't have anyway) – Rasmus Damgaard Nielsen May 23 '20 at 09:31
20

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.

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_ptr which is (reference counted)

So to recreate the example above 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
}
Doug T.
  • 64,223
  • 27
  • 138
  • 202
9

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.

its never best to use the heap... just unavoidable. :)

jheriko
  • 3,043
  • 1
  • 21
  • 28
  • It's better than a couple of assembler operations - it's just one add or subtract (depending on which direction your stack grows). – Eclipse Sep 19 '08 at 16:55
  • adds and subtracts are not always single ops... but also consider the clean up at the other end. depending on the call convention there is going to be a sub/add to match the add/sub although these may all be coalesced depending on exactly how you use the stack and what optimisations the compiler does (it may actually boil down to zero instructions... or in very special cases, minus instructions) – jheriko Dec 11 '14 at 10:49
9

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.

Kluge
  • 3,567
  • 3
  • 24
  • 21
3

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.

Kyle Cronin
  • 77,653
  • 43
  • 148
  • 164
0

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.

Engineer
  • 8,529
  • 7
  • 65
  • 105
ugasoft
  • 3,778
  • 7
  • 27
  • 23