11

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.

3
  • 2
    If you do not want dynamic memory allocation then why are you using pointers? You can might as well work with an array of Object. Commented Nov 23, 2013 at 5:12
  • 1
    Why do you want to store pointers in the first place? Commented Nov 23, 2013 at 5:12
  • 1
    The problem with you second method is that's it's not legal C++. Object ar[n]; is not legal unless n is a constant. Also since according to your edit you have a class hierarchy but with Object ar[n]; you only have Objects, not Superobjects. BTW your first method is also wrong for the reason that you are storing the addresses of objects which have been destroyed. I would just use dynamic memory allocation. Commented Nov 23, 2013 at 6:53

3 Answers 3

9

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

Sign up to request clarification or add additional context in comments.

Comments

6

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.

1 Comment

Please, unless you NEED shared_ptr semantics, don't do this. Just use boost.org/doc/libs/1_55_0/libs/ptr_container/doc/….
3

No there is no memory leak in your version. When the program leaves your scope the vector as well the array are destroyed. To your second question: Why not simply store the objects directly in an vector?

vector<Object> v;

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.