Des5car7es
Des5car7es

Reputation: 41

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

If I use this line

std:vector<MyObject>* vec = new std::vector<MyObject>(100);
MyObject obj1;
vec->push_back(obj1);

And if so, what about objects and primitives inside each MyObject ? Should they also be dynamically created ?

Thank You

Upvotes: 3

Views: 919

Answers (3)

bb1950328
bb1950328

Reputation: 1589

A std::vector<MyObject> looks something like this (in reality it's much more complex):

struct Vector {
    MyObject* data;
    int size;
}

As you can see, the data is not directly inside the vector object. The vector always allocates the memory for the data on the heap. Here's what happens when:

  • you call .push_back: The vector copies the object into its own data block (which is on the heap and owned by the vector)
  • you copy the vector: The copied vector allocates new memory and copies all data from the existing vector into it

As you can see, the vector owns his data. That means, if you push_back a object into it, it doesn't matter where it came from because it gets copied.

If you have a std::vector<MyObject>* you have a pointer to a vector. This vector also owns his data, but you only have a pointer to it. That means, you have to delete it exactly once, otherwise you'll get a memory leak or a crash. Passing around pointers to a vector is OK, but need one class or function that "owns" it. This class/function has to guarantee that the vector still exists when the pointer to it is used.

The third case is a std::vector<MyObject*>. As every vector, this one also owns his data. But this time, the data is only a pointer. So the vector only owns the pointer, but not the objects to which the pointers are pointing. If you do something like this:

std::vector<MyObject*> getObjects() {
    MyObject obj1("foo");
    MyObject obj2("bar");
    std::vector<MyObject*> vec;
    vec.push_back(&obj1);
    vec.push_back(&obj2);
    return vec;
}

The returned vector only contains garbage because you only saved the address to a object on the stack to it. These objects are destroyed when the function returns, but the pointers in the vector are still pointing to that memory block on the stack.

Upvotes: 1

daskalgg
daskalgg

Reputation: 13

Additionally, keep in mind that this

std:vector<MyObject*>* vec = new std::vector<MyObject*>(100);

Doesn't store heap allocated objects to the vector. It just stores pointers of type MyObject. If you want to do something like that remember to create the objects first, before you use them. You can do that with something like the following:

  for (int i = 0; i < vec->size(); i++) {
    vec->at(i) = new MyObject();
  }

Upvotes: 0

rawrex
rawrex

Reputation: 4064

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.

Upvotes: 7

Related Questions