The Heap and new
The Heap
You said ”it would be great it we only had to allocate and initialize an Elephant when we actually need one”, but how can we allocate an
Elephant
when we need it? I thought we had to allocate everything when the function starts.Good point! It's true that everything in the stack frame is allocated when the function starts.
But, we're not going to put our
Elephant
s on the stack!
In addition to the stack, there is another region of memory called the heap.
The stack, as we know, stores the values of local variables in each function call. Stack memory is allocated when a function is called and deallocated when that function returns.
But heap memory is allocated and deallocated whenever we tell it to be! So memory can be allocated while a function is executing and it can then persist even after a function returns.
Note that stacks are a kind of data structure, and “the stack” used by our program is actually organized as a stack—calling a function pushes a new stack frame onto the stack, and returning pops the most recent stack frame off the stack.
There's also a data structure called a heap (you may or may not have heard of it), but “the heap” used by our program is not organized like that data structure.
Here “heap” just refers to the fact that we have a disorganized pile of stuff
The new
Keyword
The line
int* p = new int{42};
allocates and initializes a single integer on the heap with the value 42.
Let's walk through what happens in this little snippet!
Key idea: The new
keyword
- Allocates space on the heap for the given type
- Initializes the data as specified
- Returns a pointer to the new piece of data
We have terms to distinguish different ways of allocating memory:
- Static allocation: memory that is allocated for the entire duration of the program (e.g., a
static
data member in a class—there isn't a separate one for each object of that class, there is exactly one for the entire program) - Automatic allocation: memory allocated on the stack (because it is allocated/deallocated automatically when functions begin/end)
- Dynamic allocation: memory allocated on the heap (because the allocation is "dynamically" determined at runtime as opposed to compile time)
The new
keyword is used for dynamic allocation.
Elephants on Demand
Oh, I see. If our array contains pointers to
Elephants
, then we can point them to anew Elephant
whenever it's time to make one.Yup, that's where we are heading.
Say we have an array of pointers,
Elephant* elephants[5];
And now, imagine that we want to create the first Elephant
with the name “Peanut” and the age set to 2.
Answer:
elephants[0] = new Elephant{"Peanut", 2};
One possible answer is
cout << elephants[0]->getName() << endl;
Some other correct answers using less-preferred syntax are
cout << (*elephants[0]).getName() << endl;
cout << (*elephants)->getName() << endl;
cout << (**elephants).getName() << endl;
Let's go through those answers real quick to make sure they make sense.
(When logged in, completion status appears here.)