As we have seen before, the term static generally refers to things that are done or known at compile time, while dynamic refers to things that happen at runtime. Although all the stack based memory is not actually allocated until the program runs, it is still considered static because the amount of memory needed for each function is known at compile time. In contrast, allocations made to the heap are considered dynamic because the amount of memory needed can change at runtime.
#include <iostream>
#include <string>
using namespace std;
void foo() {
// Stack based memory
int y = 2;
// Heap based memory
new int(5);
new string("Hello, world");
// --end of foo()--
}
int main() {
int x = 1;
foo();
// --after foo() returns--
}
At the point where the comment indicating the end of foo is, the memory layout would look something like this:
Notice that the 5 and Hello, world are stored on the heap, while x and y are stored on the stack in frames associated with main and foo, respectively. Also notice that items on the heap do not have identifiers (names). As written, there is no way to access those pieces of memory! We will solve that problem in a minute, but for now, letβs look at what happens after foo returns.
When foo returns, the stack frame for foo is destroyed, and y is no longer accessible. However, the memory allocated on the heap for the int and string still exists. This is a key feature of dynamic memory: it persists beyond the scope in which it was allocated. Back in main, where the comment indicates foo() has ended, the memory would now look like:
So how do we access the dynamically allocated memory if they do not have identifiers? The answer is to keep track of the pointers to the allocated memory. When we use new, it returns a pointer to the allocated memory. We can store this pointer in a variable, and then use it later to access the memory.
This improved version of the code creates pointers to store the addresses of the dynamically allocated memory. When new is called, the value it returns is stored into one of the pointers. We can then use those pointers to access the heap memory:
Stack based variables have identifiers (names) that allow us to access them easily. Heap based values do not have identifiers, so we must use pointers to access them. Every heap memory access will start from a stack based variable that points to the heap allocated memory.