How do I choose heap allocation vs. stack allocation in C++?
Asked Answered
B

2

20

One of the C++ features that sets it apart from other languages is the ability to allocate complex objects as member variables or local variables instead of always having to allocate them with new. But this then leads to the question of which to choose in any given situation.

Is there some good set of criteria for choosing how to allocate variables? When should I declare a member variable as a straight variable instead of as a reference or a pointer? When should I allocate a variable with new rather than use a local variable that's allocated on the stack?

Baste answered 1/11, 2011 at 21:27 Comment(2)
Do you understand that values and pointers have different semantics? That should be your first decision point.Quodlibet
@R.MartinhoFernandes: I am well aware of this. But in almost all places where you could have value semantics you could also have pointer semantics. A pointer is just a value after all.Baste
G
24

One of the C++ features that sets it apart from other languages

... is that you have to do memory allocation manually. But let's leave that aside:

  • allocate on the heap when an object has to be long-lived, i.e. must outlive a certain scope, and is expensive or impossible to copy or move,
  • allocate on the heap when an object is large (where large might mean several kilobytes if you want to be on the safe side) to prevent stack overflows, even if the object is only needed temporarily,
  • allocate on the heap if you're using the pimpl (compiler firewall) idiom,
  • allocate variable-sized arrays on the heap,
  • allocate on the stack otherwise because it's so much more convenient.

Note that in the second rule, by "large object" I mean something like

char buffer[1024 * 1024];  // 1MB buffer

but not

std::vector<char> buffer(1024 * 1024);

since the second is actually a very small object wrapping a pointer to a heap-allocated buffer.

As for pointer vs. value members:

  • use a pointer if you need heap allocation,
  • use a pointer if you're sharing structure,
  • use a pointer or reference for polymorphism,
  • use a reference if you get an object from client code and the client promises to keep it alive,
  • use a value in most other cases.

The use of smart pointers is of course recommended where appropriate. Note that you can use a reference in case of heap allocation because you can always delete &ref, but I wouldn't recommend doing that. References are pointers in disguise with only one difference (a reference can't be null), but they also signal a different intent.

Geophilous answered 1/11, 2011 at 21:33 Comment(4)
+1, but I think we should mention RVO for your first point. That one makes lots of situations where both of your points are true, still fine to allocate on the stack (i.e some helper function that returns some object).Anosmia
+1 You might also add polymorphic contexts where the concrete type is not determinable at compile time. Although polymorphism doesn't neccessarily imply dynamic allocation.Hallvard
This doesn't address whether or not a member variable should be a pointer or included by value. And there are things like the pimpl idiom to consider.Baste
@Omnifarious: added some hints on when to use pointer members.Geophilous
M
2

There is little to add to the answer of larsmans.

Allocating on the stack usually simplifies resource management, you do not have to bother with memory leaks or ownership, etc. A GUI library is built around this observation, check at "Everything belongs somewhere" and "Who owns widgets."

If you allocate all members on the stack then the default copy ctor and default op= usually suffices. If you allocate the members on the heap, you have to be careful how you implement them.

If you allocate the member variable on the stack, the member's definition has to be visible. If you allocate it on the heap then you can forward declare that member. I personally like forward declarations, it reduces dependency.

Milepost answered 1/11, 2011 at 21:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.