Local variables are on the stack, along with function parameters. Code is in code space,
of course, and global variables are in the global namespace. Registers are used for internal
housekeeping functions, such as keeping track of the top of the stack and the instruction
pointer. Just about all the remaining memory is given to the free store, which is
often referred to as the heap.

Local variables don’t persist; when a function returns, its local variables are destroyed.
This is good because it means the programmer doesn’t have to do anything to manage
this memory space. But is bad because it makes it hard for functions to create objects for
use by other objects or functions without generating the extra overhead of copying
objects from stack to return value to destination object in the caller. Global variables
solve that problem at the cost of providing unrestricted access to those variables throughout
the program, which leads to the creation of code that is difficult to understand and
maintain. Putting data in the free store can solve both of these problems if that data is
managed properly.

You can think of the free store as a massive section of memory in which thousands of
sequentially numbered cubbyholes lie waiting for your data. You can’t label these cubbyholes,
though, as you can with the stack. You must ask for the address of the cubbyhole
that you reserve and then stash that address away in a pointer.

One way to think about this is with an analogy: A friend gives you the 800 number for
Acme Mail Order. You go home and program your telephone with that number, and then
you throw away the piece of paper with the number on it. If you push the button, a telephone
rings somewhere, and Acme Mail Order answers. You don’t remember the number,
and you don’t know where the other telephone is located, but the button gives you
access to Acme Mail Order. Acme Mail Order is your data on the free store. You don’t
know where it is, but you know how to get to it. You access it by using its address—in
this case, the telephone number. You don’t have to know that number; you just have to
put it into a pointer (the button). The pointer gives you access to your data without bothering
you with the details.

The stack is cleaned automatically when a function returns. All the local variables go out
of scope and they are removed from the stack. The free store is not cleaned until your
program ends, and it is your responsibility to free any memory that you’ve reserved
when you are done with it. This is where destructors are absolutely critical: They provide
a place where any heap memory allocated in a class can be reclaimed.

The advantage to the free store is that the memory you reserve remains available until
you explicitly state you are done with it by freeing it. If you reserve memory on the free
store while in a function, the memory is still available when the function returns.
The disadvantage of the free store is also that the memory you reserve remains available
until you explicitly state you are done with it by freeing it. If you neglect to free that
memory, it can build up over time and cause the system to crash.

The advantage of accessing memory in this way, rather than using global variables, is
that only functions with access to the pointer (which has the appropriate address) have
access to the data. This requires the object containing the pointer to the data, or the
pointer itself, to be explicitly passed to any function making changes, thus reducing the
chances that a function can change the data without that change being traceable.
For this to work, you must be able to create a pointer to an area on the free store and to
pass that pointer among functions.​