Object creation on the stack/heap?

The following code creates an object on the stack:

Object o;

When creating an object on the heap we can use:

Object* o;

o = new Object();

rather than:

Object* o = new Object();

When we split the heap object-creation over two lines and call the constructor on the second line (o = new object()), does this mean in the first line (Object* o) the pointer was created on the stack? So Object o puts the object on the stack, whereas Object* o puts the pointer to a future object on the stack?

My second question involves if the two lines of code were called outside of a class. I recently read (Global memory management in C in stack or heap?) that global variables are not contained on the stack/heap but actually another part of memory? If this is the case, would Object* o create a pointer which would sit in this other part of the memory and it points to the heap object?


Solution 1:

Actually, neither statement says anything about heap or stack. The code

Object o;

creates one of the following, depending on its context:

  • a local variable with automatic storage,
  • a static variable at namespace or file scope,
  • a member variable that designates the subobject of another object.

This means that the storage location is determined by the context in which the object is defined. In addition, the C++ standard does not talk about stack vs heap storage. Instead, it talks about storage duration, which can be either automatic, dynamic, static or thread-local. However, most implementations implement automatic storage via the call stack, and dynamic storage via the heap.

Local variables, which have automatic storage, are thus created on the stack. Static (and thread-local) objects are generally allocated in their own memory regions, neither on the stack nor on the heap. And member variables are allocated wherever the object they belong to is allocated. They have their containing object’s storage duration.

To illustrate this with an example:

struct Foo {
    Object o;
};

Foo foo;

int main() {
    Foo f;
    Foo* p = new Foo;
    Foo* pf = &f;
}

Now where is the object Foo::o (that is, the subobject o of an object of class Foo) created? It depends:

  • foo.o has static storage because foo has static storage, and therefore lives neither on the stack nor on the heap.
  • f.o has automatic storage since f has automatic storage (= it lives on the stack).
  • p->o has dynamic storage since *p has dynamic storage (= it lives on the heap).
  • pf->o is the same object as f.o because pf points to f.

In fact, both p and pf in the above have automatic storage. A pointer’s storage is indistinguishable from any other object’s, it is determined by context. Furthermore, the initialising expression has no effect on the pointer storage.

The pointee (= what the pointer points to) is a completely different matter, and could refer to any kind of storage: *p is dynamic, whereas *pf is automatic.

Solution 2:

C++ offers three different ways to create objects:

  1. Stack-based such as temporary objects
  2. Heap-based by using new
  3. Static memory allocation such as global variables and namespace-scope objects

Consider your case,

Object* o;
o = new Object();

and:

Object* o = new Object();

Both forms are the same. This means that a pointer variable o is created on the stack (assume your variables does not belong to the 3 category above) and it points to a memory in the heap, which contains the object.

Solution 3:

The two forms are the same with one exception: temporarily, the new (Object *) has an undefined value when the creation and assignment are separate. The compiler may combine them back together, since the undefined pointer is not particularly useful. This does not relate to global variables (unless the declaration is global, in which case it's still true for both forms).

Solution 4:

C++ has Automatic variables - not Stack variables.

Automatic variable means that C++ compiler handles memory allocation / free by itself. C++ can automatically handle objects of any class - no matter whether it has dynamically allocated members or not. It's achieved by strong guarantee of C++ that object's destructor will be called automatically when execution is going out of scope where automatic variable was declared. Inside of a C++ object can be a lot of dynamic allocations with new in constructor, and when such an object is declared as an automatic variable - all dynamic allocations will be performed, and freed then in destructor.

Stack variables in C can't be dynamically allocated. Stack in C can store pointers, or fixed arrays or structs - all of fixed size, and these things are being allocated in memory in linear order. When a C program frees a stack variable - it just moves stack pointer back and nothing more.

Even though C++ programs can use Stack memory segment for storing primitive types, function's args, or other, - it's all decided by C++ compiler, not by program developer. Thus, it is conceptually wrong to equal C++ automatic variables and C stack variables.

Solution 5:

In both your examples, local variables of Object* type are allocated on the stack. The compiler is free to produce the same code from both snippets if there is no way for your program to detect a difference.

The memory area for global variables is the same as the memory area for static variables - it's neither on the stack nor on the heap. You can place variables in that area by declaring them static inside the function. The consequence of doing so is that the instance becomes shared among concurrent invocations of your function, so you need to carefully consider synchronization when you use statics.

Here is a link to a discussion of the memory layout of a running C program.