1

I have a big doubt about dynamic allocation. Suppose you have a class like this:

class MyClass {
    public:
        MyClass() {}
        ~MyClass() {}
    private:
        std::vector<MyOtherClass> others;
};

If I create an instance of MyClass using new MyClass, the inner vector wil be allocated in heap or on stack?

1
  • You have to appreciate that std::vector itself is an object that contains a pointer to an array. Thus, the "vector" object (the object of class std::vector) is on the stack inside MyClass, while the internal array that the vector points to is on the heap.
    – Erik Eidt
    Sep 25, 2017 at 9:12

4 Answers 4

1

Note: implementations don't have to have 'stacks' and 'heaps' but they are pretty common implementation artifacts.

If you create a "local" instance of MyClass (ie. an automatic variable) then its memory will be on the stack. The 'others' member variable will typically take up a couple of 'words' in memory (eg. a 'word' might be 32 bits); one for the vectors size variable and a pointer to dynamic memory for the vector's members. The dynamic memory will be allocated on the heap by something like malloc().

3

If I create an instance of MyClass using new MyClass, the inner vector will be allocated in heap or on stack?

You should not care (since it is an implementation detail). What you need to be concerned with is that any resource created (for the inner vector) at construction time will properly be released at destruction time; and any well behaved class should obey that rule (unless it is documenting otherwise). Read about RAII and the wikipage on Criticism of C++. Be aware of the rule of five.

In practice, automatic variables of std::vector type are likely to keep their internal data in some heap allocated memory (which is deleted by the vector's destructor), but the vector's length and the pointer to that internal data is probably on the call stack. For std::string-s it is likely (but not required) to be different: read about small string optimizations (in some cases, the string's data remains on the call stack).

Notice that a call stack is not always required (but practically present). The C++11 or the C11 specification don't require any call stack. An (hypothetical) optimizing compiler could be clever enough to avoid needing a call stack for your program.

If you really care, study the machine code produced by your particular compiler. With GCC (at least on Linux), compile yourprog.cc source file using g++ -Wall -S -O yourprog.cc then look into the generated yourprog.s assembler file.

But you should not care about where is a data located (on heap or on stack). You need to be sure it would be appropriately released (by destructors).

You would care (about call frame size) for benchmarking and performance reasons; then use the compiler, for example use g++ with -Wstack-usage=800

In your own code, the only way to get heap allocated data is to use ::operator new or to call some function which uses it. Of course delete (or some function using it) should later be used to avoid memory leaks.

In your own code, the destructors of member fields (e.g. others in your case) would be called after the (currently empty) body of your destructor ~MyClass().

3
  • 1
    "An (hypothetical) optimizing compiler could be clever enough to avoid needing a call stack for your program." -- or you may alternatively be using an extended version of C++ that provides features that aren't compatible with using traditional call stacks, e.g. first-class continuations, and therefore find all your activation frames are allocated on the heap anyway.
    – Jules
    Sep 25, 2017 at 10:43
  • Yes. However, do you know any existing Continuation Passing Style C++ compiler? If yes, share that information with us, please. I'm interested Sep 25, 2017 at 10:45
  • I've definitely read a report that was written by somebody who was working on one a year or so back, but unfortunately I can't find it any more.
    – Jules
    Sep 25, 2017 at 10:57
1

A quick browse through C++14 November 2014 working draft, we get the point 18.6.1.1:

void* operator new(std::size_t size);

1 Effects: The allocation function (3.7.4.1) called by a new-expression (5.3.4) to allocate size bytes of storage suitably aligned to represent any object of that size.

Which can be read as, when you new an object, a single piece of memory is created to store all of its members. However, only the vector itself is in that first allocation. The members of the vector are a dynamically allocated array and as such will be somewhere else in memory.

This means that if you create an instance of MyClass as a local, the inner vector others will be local as well. If you create an instance of MyClass in heap memory, others will be on the heap. To be precise: calling new means your inner vector will be on the heap, included in your instance of MyClass, assuming new actually allocates to heap (which is standard in most compilers).

3
  • As informative as this answer is, it doesn't outright answer his question, "will the inner vector be allocated in heap or on stack?" Please provide the direct answer even if you think it is evident.
    – Neil
    Sep 25, 2017 at 8:43
  • 1
    @Neil Thanks to your comment I've improved my answer to include a more precise answer to the question. I hope that makes it clearer. :) Sep 25, 2017 at 9:46
  • 1
    "To be precise: calling new means your inner vector will be on the heap" -- the standard doesn't specify that, however. It just states that memory is allocated, but not where. An optimizing compiler, for example, may be able to deduce that the object doesn't escape the current call and convert it to a stack allocation, and the C++ standard does not prevent it doing so. (I don't know whether any current C++ compilers do this, but it is certainly a feasible optimization that is performed by other language implementations, so I would not be surprised if it is done in C++ too)
    – Jules
    Sep 25, 2017 at 10:48
0

What follows represents what usually happens in C++. At the end I cover some possible reasons why it may not be the case.

Usually, when you write MyClass *clz = new MyClass();, the new operator will allocate sizeof MyClass bytes on the heap, call the constructor of its member and return a pointer to the allocated memory.

As you're including the vector as a member, any members of the vector will be included in the sizeof MyClass heap allocation. This is implementation dependent but is usually a size, capacity and a pointer to another heap allocation which is used for a variable sized array of MyOtherClasses. In other words, you may get 2 heap allocations with the original new.

If, however, you just included MyClass clz; as a local variable, the sizeof MyClass will be allocated on the stack. The valriable array within the vector may still be allocated on the heap however.

But, this being C++, the above may not be true. Firstly, one can override the new operator to do something else. In theory you could make it allocate on the stack, using alloca say, though this would be a spectacularly bad idea.

Secondly, the implementation of std::vector can vary considerably. One optimisation, known as the small vector optimisation, stores a few objects in its struct rather than on the heap if it can. Under certain circumstances this can improve performance though is probably unlikelty in your case (depends on the implementation of vector and MyOtherClass). Also, and more likely in your case, the implementation may not do an internal heap allocation until you insert something. So the new MyClass doesn't do 2 heap allocations but you may well get one or more as you fill the vector in the running program.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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