1

I need some clarification on C++ memory allocation, I'll just get right to an example

Let's say I have made a class A, which contains two containers: a hash_map and a std::vector like this:

class Example{

// methods to add stuff to containers
//...

std::hash_map<std::string,int> map;
std::vector<std::string> vec;
}

If I then create an object of example on the heap using the new operator:

Example* ex = new Example();

and add a thousand entries to each container, will the entries I add be located on the heap as well? If yes, then what would be different if I did:

 class Example{

    // methods to add stuff to containers
    //...

    std::hash_map<std::string,int>* map;
    std::vector<std::string>* vec;
    }

and then Example* ex = new Example();

trincot
  • 317,000
  • 35
  • 244
  • 286
user2573715
  • 47
  • 1
  • 5

4 Answers4

5

No matter where a hash_map or vector is stored, the data that they contain will always be in the heap.

Example 1

int main() {
    hash_map<T> table;
}

table is on the stack. The data that table contains is on the heap.

Example 2

int main() {
    hash_map<T> *table = new hash_map<T>();
}

table is a pointer that exists on the stack. *table is a hash_map that exists on the heap. The data that *table contains is still on the heap.

Example 3

hash_map<T> table;
int main() {
    ...
}

table is not in the heap or stack. The data table points to is still on the heap.

Bill Lynch
  • 80,138
  • 16
  • 128
  • 173
3

The data items in both containers will always be in the heap; The difference between having std::hash_map map and std::hash_map *map is that in the first case your Example object holds actual object map (which, in particular, will be automatically destroyed when Example object is destroyed), while in the second case your Example object only holds a pointer to the object map (which is probably created/destroyed elsewhere).

michaelb
  • 451
  • 2
  • 11
2

new Example(); This statement always means allocate a single Example object on the heap and return the pointer to that object.

Example ex; is the way to allocate a single Example object on the stack.

The differences you describe are in the content of an Example object. In the first instance the object holds instances of an stl vector and a hash_map directly (they are constructed with the object and released with it)

In the second instance the object holds pointers the containers and what you put on these pointers is left open.

In any case the vector and hash_map would use the heap to store the data you insert into them, But they hide the details and the management from you. (You can supply allocators to mess with defaults )

Advanced Note: Example ex; when in the scope of a function / method would allocate the object on the stack. The object is released when the scope exits. When used inside a namespace or global scope it would allocate the object in the data segment and the object is released when the program terminates.

odedsh
  • 2,594
  • 17
  • 17
1

In both cases, your object will be instantiated on the heap. The new operator does that.

The difference between your two examples is that in the first one, without using * for the two members, they are implicitly constructed as part of your object when you call new Example() (in memory, your object layout will contain a hash_map and a vector of sizes sizeof(hash_map) and sizeof(vector)).

In the second case, when you are declaring the members as pointers, your object layout in memory will only contains 2 sizeof(void*) - basically size of pointer, all pointers are equal in size regardless of the type they point to. This also means that, when you instantiate your class with new Example(), your members will by default be nullptr, so you have to explicitly initialize each of them with new hash_map and new vector in order to use them.

As for stack allocation, if you want an instance of your Example class to be allocated on the stack, in a function you would use

Example foo;

instead of

Example* foo = new Example();

This will allocate foo on the stack and destroy it automatically when the function returns.

vladris
  • 156
  • 1
  • 4
  • It is possible for pointers to things to have different sizes: http://stackoverflow.com/questions/6751749/size-of-a-pointer And `foo` is destroyed when it goes out of scope, not when the function returns. – Bill Lynch Apr 05 '15 at 15:29