When and why to declare member variables on the heap C++
Asked Answered
D

5

20

Ok, so I'm very new at C++ programming, and I've been looking around for a couple days for a decisive answer for this. WHEN should I declare member variables on the heap vs. the stack? Most of the answers that I've found have dealt with other issues, but I want to know when it is best to use the heap for member variables and why it is better to heap the members instead of stacking them.

Docent answered 13/7, 2012 at 19:59 Comment(1)
member variables refer to class members, and as such go where the instance of the class goes.Phosphoresce
D
30

There are two important concepts to grasp first:

  1. One should avoid thinking in terms of "heap" and "stack". Those are implementation details of your compiler/platform, not of the language.1 Instead, think in terms of object lifetimes: should the object's lifetime correspond to that of its "parent", or should it outlive it? If you need the latter, then you'll need to use new (directly or indirectly) to dynamically allocate an object.

  2. Member variables always have the same lifetime as their parent. The member variable may be a pointer, and the object it points to may well have an independent lifetime. But the pointed-to object is not a member variable.

However, there is no general answer to your question. Crudely speaking, don't dynamically allocate unless there is a good reason to. As I hinted above, these reasons usually correspond to situations where the lifetime needs to differ from its "parent".


1. Indeed, the C++ standard doesn't really talk about "heap" and "stack". They're important to consider when optimising or generally thinking about performance, but they're mostly irrelevant from a program-functionality point of view.
Demoiselle answered 13/7, 2012 at 20:4 Comment(6)
"usually correspond to situations where the lifetime needs to differ from its parent": can we still speak of something as a member then?Coercive
@JamesKanze: Indeed, I should clarify that.Demoiselle
Objects also require dynamic lifetime if they are dynamically sized, or for casting an object to a virtual base class.Accountancy
@MooingDuck: Agree with dynamic sizing (although you could argue that that's really a lifetime issue again). Not sure about the point about base classes though, although that requires pointers (or references), dynamic allocation isn't necessarily required.Demoiselle
@OliCharlesworth: no, dynamic size is not even remotely related to lifetime. You're right that a container of base pointers doesn't require heap allocation, but it's nearly useless without it.Accountancy
@MooingDuck: Re: dynamic sizing; I was thinking in terms of resizing. I guess you're talking about general "size not known at compile-time"?Demoiselle
C
5

Member variables are members of the class itself. They are neither on the heap nor on the stack, or rather, they are where ever the class itself is.

There are very few reasons to add a level of indirection, and allocate a member separately on the heap: polymorphism (if the type of the member is not always the same) is by far the most common.

Coercive answered 13/7, 2012 at 20:10 Comment(5)
Objects also require dynamic lifetime if they are dynamically sized, or for casting an object to a virtual base class.Accountancy
@MooingDuck Objects which are dynamically sized should be managed by their own class (e.g. std::vector): you don't allocate them as members; you make the container the member. And casting to a virtual base class or whatever implies that the member is polymorphic, which is what I mentionned.Coercive
Polymorphysm doesn't require heap allocation. Consider: Derived x; Base* y=&x; There is no heap allocation taking place here.Marrowfat
@Marrowfat There's also no need for polymorphism. If a member of a class is to have polymorphic behavior, it will almost always have to be allocated dynamically. (There are exceptions, of course, but they are few and far between.)Coercive
@James Kanze: everybody always says that std::vector must be used for dynamically sized objects. But you always forget the systems where you have C++ compiler but you don't have STL. Not all C++ system has STL. (see some smaller embedded environment).Expanse
U
2

To get some terminology straight: What you call a heap and stack describe the lifetime of objects. The first means that the lifetime is dynamic, the second automatic and the third (which you don't mention) is static.

Usually you will need dynamic lifetime of an object when it should outlive the scope it was created in. Another common case is when you want it to be shared across different parent objects. Also, dynamic lifetime is also necessary when you work with a design that is heavyly object-oriented (uses a lot of polymorphism, doesn't use values), e.g. Qt.

An idiom that requires dynamic lifetimes is the pimpl-idiom.

Most generic-programming libraries are more focused towards value and value-semantics, so you won't use dynamic binding that much and automatic lifetimes become a lot more common.

There are also some examples where dynamic allocation is required for more implementation specific reasons:

  • dynamically sized objects (containers)
  • handling incomplete types (see pimpl-idiom)
  • easy nullability of a type

All of those are just general guidelines and it has to be decided on a case by case basis. In general, prefer automatic objects over dynamic ones.

Unintelligible answered 13/7, 2012 at 20:10 Comment(0)
K
1

The stack refers to the call stack. Function calls, return addresses, parameters, and local variables are kept on the call stack. You use stack memory whenever you pass a parameter or create a local variable. The stack has only temporary storage. Once the current function goes out of scope, you no longer have access to any variables for parameters.

The heap is a large pool of memory used for dynamic allocation. When you use the new operator to allocate memory, this memory is assigned from the heap. You want to allocate heap memory when you are creating objects that you don't want to lose after the current function terminates (loses scope). Objects are stored in the heap until the space is deallocated with delete or free().

Keats answered 13/7, 2012 at 20:8 Comment(1)
Objects also require dynamic lifetime if they are dynamically sized, or for casting an object to a virtual base class.Accountancy
F
0

Consider this example:

You implement a linked list which has a field member head of class node.
Each node has a field member next. If this member of the type Node and not Node* the size of every Node would depend on the number of the nodes after it in the chain.

For example, if you have 100 nodes in your list your head member will be huge. Because it holds the next node inside itself so it needs to have enough size to hold it and next holds the next and so on. So the head has to have enough space to hold in it 99 nodes the next 98 and so on...

You want to avoid that so in this case it's better to have pointer to to next node in each Node rather than the next node itself.

Forsythia answered 7/4, 2017 at 6:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.