Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating c++ vector of pointers

In my C++ code I have a class Object equipped with an id field of type int. Now I want to create a vector of pointers of type Object*. First I tried

vector<Object*> v;

for(int id=0; id<n; id++) {
    Object ob = Object(id);
    v.push_back(&ob);
}

but this failed because here the same address just repeats itself n times. If I used the new operator I would get what I want but I'd like to avoid dynamic memory allocation. Then I thought that what I need is somehow to declare n different pointers before the for loop. Straightforward way to this is to declare an array so I did this :

vector<Object*> v;
Object ar[n];

for(int i=0; i<n; i++) {
    ar[i] = Object(i);
}

for(int i=0; i<n; i++) {
    v.push_back(ar+i);
}

Is there still possibility to get a memory leak if I do it this way? Also going through an array declaration is a bit clumsy in my opinion. Are there any other ways to create vector of pointers but avoid manual memory management?

EDIT: Why do I want pointers instead of just plain objects?

Well I modified the original actual situation a bit because I thought in this way I can represent the question in the simplest possible form. Anyway I still think the question can be answered without knowing why I want a vector of pointers.

Actually I have

Class A {
protected:
    vector<Superobject*> vec;
...
};

Class B: public A {...};

Class Superobject {
protected:
    int id;
...
}

Class Object: public Superobject {...}

In derived class B I want to fill the member field vec with objects of type Object. If the superclass didn't use pointers I would have problems with object slicing. So in class B constructor I want to initialize vec as vector of pointers of type Object*.

EDIT2

Yes, it seems to me that dynamic allocation is the reasonable option and the idea to use an array is a bad idea. When the array goes out of scope, things will go wrong because the pointers in vector point to memory locations that don't necessarily contain the objects anymore.

In constructor for class B I had

B(int n) {
    vector<Object*> vec;
    Object ar[n];

    for(int id=0; id<n; id++) {
        ar[id] = Object(id);
    }

    for(int id=0; id<n; id++) {
        v.push_back(ar+id);
    }
 }

This caused very strange behavior in objects of class B.

like image 776
Parzival Avatar asked Nov 23 '13 05:11

Parzival


2 Answers

In this loop:

for(int id=0; id<n; id++) {
    Object ob = Object(id);
    v.push_back(&ob);
}

You are creating n times Object instance on stack. At every iteration there is created and removed element. You can simply avoid this using that:

for(int id=0; id<n; id++) {
    Object* ob = new Object(id);
    v.push_back(ob);
}

thanks that every new element exist on heap not on the stack. Try to add to in class Object constructor something like that:

std::cout<<"Object ctor()\n";

and the same in the destructor:

std::cout<<"Object dtor()\n";

If you dont want to create these objects with "new" try reason written by @woolstar

like image 182
marcinioski Avatar answered Oct 06 '22 22:10

marcinioski


Your question about memory leaks makes me think you are worried about the lifecycle and cleanup of these objects. I originally proposed shared_ptr wrappers, but C++11 gave us unique_ptr, and C++14 filled in the missing make_unique. So with all that we can do:

vector<unique_ptr<SuperObject>> v ;

Which you create in place with the wonderfulness of perfect forwarding and variadic templates,

v.push_back( make_unique<Object>( ... ) ) ;

Yes you are going to have to live with some heap allocations, but everything will be cleaned up when v goes away.

Someone proposed a boost library, ptr_container, but that requires not only adding boost to your project, but educating all future readers what this ptr_container is and does.

like image 38
woolstar Avatar answered Oct 06 '22 20:10

woolstar