When Vectors Are Allocated, Do They Use Memory on the Heap or the Stack

When vectors are allocated, do they use memory on the heap or the stack?

vector<Type> vect;

will allocate the vector, i.e. the header info, on the stack, but the elements on the free store ("heap").

vector<Type> *vect = new vector<Type>;

allocates everything on the free store.

vector<Type*> vect;

will allocate the vector on the stack and a bunch of pointers on the free store, but where these point is determined by how you use them (you could point element 0 to the free store and element 1 to the stack, say).

Is it possible to allocate vectors in the heap but accessing via reference?

  1. Unlike std::array, std::vector does not store elements inside itself, it always allocates storage on the heap (unless you use a custom allocator). Your 2.5 MB go into the heap, and only std::vector itself (a couple of pointers and the size, 12/24 bytes, typically) is allocated on the stack.

  2. You can do it:

    void foo(std::vector<T>&);

    std::vector<T>* vec = ...;
    foo(*vec);

Edit. I found a duplicate question. Voted to close this one.

Stack vs Heap - Should objects inside *vector be declared as pointers?

The std:vector as any other Standard Library container copies elements into itself, so it owns them. Thus, if you have a dynamically allocated std::vector the elements that you .push_back() will be copied into the memory managed by the std::vector, thus they will be copied onto the heap.

As a side note, in some cases std::vector may move elements if it is safe to do so, but the effect is the same - in the end, all the elements are under std::vector's jurisdiction.

Where does a std::vector allocate its memory?

Does a std::vector allocate memory for its elements on the heap?

Yes. Or more accurately it allocates based on the allocator you pass in at construction. You didn't specify one, so you get the default allocator. By default, this will be the heap.

But how does it free that heap memory?

Through its destructor when it goes out of scope. (Note that a pointer to a vector going out of scope won't trigger the destructor). But if you had passed by value to sub you'd construct (and later destruct) a new copy. 5 would then get pushed back onto that copy, the copy would be cleaned up, and the vector in main would be untouched.

Allocated memory is in the stack or heap

Possibly neither. The precise terms are

  • static storage: for data that exists as long as the process exists;
  • automatic storage: for data that is allocated and fred as the process enters/exits different scopes;
  • dynamic storage: for data that must be explicitly requested and exists until it is explicitly fred.

Usually automatic memory lives in the stack and dynamic storage lives in the heap. But the compiler is completely free to implement all those storage types in whatever way they want, as long as it respects the rules for lifespan.

So:

static vector1Int hello;

is in the file scope and creates an object of type vector1Int in static storage.

And this

hello = vector1Int(8,12);

will cause std::vector to create room for at least 8 integers. We can usually assume that this will be taken from dynamic storage. However, this is not a rule. For instance, you could easily make std::vector use static or automatic memory by implementing your own allocator (not general purpose memory allocator, but STL allocator).

When your program reaches the end of the main function, the destructor of std::vector will be called for hello, and any dynamic memory that hello had requested will be given back to the memory manager.

The memory for the object hello itself is not fred because it is static. Instead, it is given back to the OS together with anything else the process used when the process terminates.

Now, if hello had been declared as a local variable of create, then the destructor would be called at the end of that function. In that case, hello would have been allocated at automatic storage, and would be fred at the end of create.

C++ vector memory allocation

As defining those as global or in other places might not go in the stack, I assume we are defining int array[1000000] or std::vector<int> array(1000000) in a function definition, i.e. local variables.

For the former, yes you're right. It is stored in the stack and due to stack space limitation, in most environment it is dangerous.

On the other hand, in most of standard library implementations, the latter only contains a size, capacity and pointer where the data is actually stored. So it would take up just a couple dozen bytes in the stack, no matter how many elements are in the vector. And the pointer is generated from heap memory allocation(new or malloc), not the stack.

Here is an example of how many bytes it takes up in the stack for each.

And here is a rough visualization.

Sample Image

If I make a struct and put it in a vector, does it reside on the heap or the stack?

The documentation for Vec says (emphasis mine):

If a Vec has allocated memory, then the memory it points to is on the heap

So yes, the members of the vector are owned by the vector and are stored on the heap.


In general, boxing an element before putting it in the Vec is wasteful - there's extra memory allocation and indirection. There are times when you need that extra allocation or indirection, so it's never say never.

See also:

  • Does Rust box the individual items that are added to a vector?

Free storage for pointers stored in a heap allocated vector

You have a misunderstanding about how types work in C++. Every type has a fixed size. You can get this size with sizeof. For example, on a typical platform, a vector<Test*> has a size of 24 bytes.

When you allocate a vector on the stack, you are only allocating those 24 bytes on the stack. When you add objects to the vector, the vector will allocate memory from the heap to store those objects.

like I said I have to stick with this implementation since it save more stack memory than storing vector on the stack.

It won't. So you don't have to stick with this implementation. Switch to a sensible one such as std::vector<std::unique_ptr<Test>>.

And I dont want objects to be copied or moved to prevent moving objects and keeping hollow ones that take more space

A sensible implementation (such as std::vector<std::unique_ptr<Test>>) won't move the underlying objects. Move semantics for std::vector are already optimal on any sensible platform.

You are expecting moving a std::unique_ptr to be significantly different from moving a std::vector. Your reasoning for that assumption is faulty and, even if it was correct, this would still be a pointless increase in complexity.

In fact, why not just use vector<Test>?

Check this out:

#include <iostream>
#include <vector>

int main()
{
std::vector<int> a;

for (int i = 0; i < 10; ++i)
a.push_back(i);

std::cout << &a[0] << std::endl;

std::vector<int> b = std::move(a);
std::cout << &b[0] << std::endl;
}

Output:

0x563caf0f1f20
0x563caf0f1f20

Notice that moving the vector didn't even move the objects in the vector. It just transferred ownership of the objects from one vector to the other.

Stop trying to optimize things that are already optimized.

How does vectors in C++ use memory?

As addressed in the comments by Kamil, a std::vector keeps track of three pointers internally. One pointer to the begin, one to end and one to the end of allocated memory (see stack post). Now, the size of a pointer should be 8 bytes on any 64-bit C/C++ compiler so, 3 * 8 bytes = 24 bytes (see wiki).



Related Topics



Leave a reply



Submit