75

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?

3
  • Those two will probably optimize to the same thing, I think.
    – Ry-
    Commented Apr 14, 2012 at 20:33
  • 30
    The pointer is always created on the stack. Commented Apr 14, 2012 at 20:36
  • 5
    I would second @leftaroundabout, and go further: all variables declared in a block are created on the stack; the whole object for the first example, and the pointer to the object in the second.
    – Phil H
    Commented Apr 14, 2012 at 20:50

7 Answers 7

147

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.

5
  • 1
    Could you please explain what you mean by "automatic storage"? Also, what would be the difference between Foo pf = new Foo(); and Foo* pf = new Foo(); ?
    – user997112
    Commented Apr 14, 2012 at 20:53
  • 12
    what would be the difference between Foo pf = new Foo(); and Foo* pf = new Foo(); -- The second would compile, while the firs one wouldn't? Commented Apr 14, 2012 at 20:58
  • Because we can only use pointers with regards to heap allocation?
    – user997112
    Commented Apr 14, 2012 at 21:04
  • @dasblinkenlight: I guess that was just a typo. The first one would give a compiler error unless there is a user-defined conversion from Foo* to Foo.
    – Philipp
    Commented Apr 14, 2012 at 22:40
  • Best answer! It's obvious that even too many experienced developers are used to refer to concepts like stack and heap instead of the actual formalized concepts you mentioned. Within the C++ standard, the word heap did never occur and even the word stack does not (only in terms of the independent call stack/stack unwinding concept). A compiler is even allowed to solely refer to heap (or fully plain static pre-allocated memory) mechanisms for both, automatic and dynamic storage duration purposes (see several embedded systems for instance).
    – Secundi
    Commented Mar 25, 2021 at 9:40
19

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.

2
  • 2
    Heap Based objects are not necessarily involve new. New is usually used for creating instances outside of a scope not bound to the life-cycle of the current instance. Everything is heap unless it is bound to the scope of the current function which allows for stack storage (if the compiler decides to do so) Commented Mar 29, 2020 at 3:09
  • @MartinKersten, could you elaborate on the difference? What can be said about creating heap-based objects? Did you phrase your comment as you did referring to life-cycle because the standard doesn't mention the heap? Commented May 9, 2023 at 18:57
6

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.

5

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).

1
  • It is likely that the compiler combines both as a declared variable is not read in between. It is a basic optimization almost every compiler does. In fact the declaration only reserves memory in the data block, on the stack or within the struct/instance. Therefore from a compiler standpoint both are actually equivalent when it comes to actual machine code. Commented Mar 29, 2020 at 3:14
1

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.

1
  • He tagged C++ and for C++ the pointer is usually heap oriented even if the compiler can determine the scope of the pointer to be local (function scope). Commented Mar 29, 2020 at 3:11
1

A)

Object* o;
o = new Object();

`` B)

Object* o = new Object();

I think A and B has no difference. In both the cases o is a pointer to class Object. statement new Object() creates an object of class Object from heap memory. Assignment statement assigns the address of allocated memory to pointer o.

One thing I would like to mention that size of allocated memory from heap is always the sizeof(Object) not sizeof(Object) + sizeof(void *).

-1
  1. Object* o; o = new Object();

  2. Object* o = new Object();

Both these statement creates the object in the heap memory since you are creating the object using "new".

To be able to make the object creation happen in the stack, you need to follow this:

Object o;
Object *p = &o;
1
  • "in the heap memory " The standard has no concept of a heap memory.
    – Secundi
    Commented Mar 25, 2021 at 9:46

Not the answer you're looking for? Browse other questions tagged or ask your own question.