Looking for a good way to populate a vector<Object*>

Hi,

As the title says I'm putting pointers to objects in a vector. The way I'm doing it right now is like follows: (object 1, 2 and 3 are all derived from the same class Object)

vector<Object*> myObjects;

Object1 myFirstObj;
Object2 mySecondObj;
Object3 myThirdObj;

Object* ObjectPtr1 = &myFirstObj;
Object* ObjectPtr2 = &mySecondObj;
Object* ObjectPtr3 = &myThirdObj;

myObjects.push_back(ObjectPtr1);
myObjects.push_back(ObjectPtr2);
myObjects.push_back(ObjectPtr3);

As I create more and more objects this will get really tedious so I'm wondering is there a more efficient way to do this? Maybe some way that you could create the object and pointer at the same time? (maybe even assign it at the same time?). One can assume that I'll know how many objects and pointer I'll need in advance.

All help will be greatly appreciated!

FYI, the way you are doing that could be bad if your objects go out of scope before the vector does:

1
2
3
4
5
6
vector<Object*> objs;
{
    Object myobj;
    objs.push_back(&myobj);
}
objs[0]->oh_crap(); //<-- bad! objs[0] points to garbage because myobj is not alive anymore 


Using heap memory easier, but you have to remember to delete the objects:

objs.push_back(new Object);
And then you can use boost::ptr_vector<>, which is the same thing as std::vector<> except
it works only for pointers, and takes care to delete the pointer when the element is removed
so you avoid the memory leak firedraco mentioned.
Ok I'll have to look out for that

objs.push_back(new Object);

wouldn't this make a new Object and not an Object* ? How would I go about if I wanted to do something like that but with pointers?

In my case I have three classes; Shape, Shape2D and Triangle (for now). Shape2D is derived from shape and Triangle is derived from Shape2D. The classes has a member function menu() in common (and some more) what I'm trying to do is something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#include <iostream>
#include <vector>
using namespace std;

#include "Shape.h"
#include "Shape2D.h" // derived from Shape
#include "Triangle.h" // derived from Shape2D

int main()
{
    int query = 0;
    int exit = 0;

    /**
     * create vector and objects
     **/
    vector<Shape*> myShapes;
    Shape myShape;
    Shape2D my2DShape;
    Triangle myTri;

    /**
     * populate vector myShapes
     **/
    Shape* shapePtr1 = &myShape;
    Shape* shapePtr2 = &my2DShape;
    Shape* shapePtr3 = &my3DShape;
    Shape* shapePtr4 = &myTri;

    myShapes.push_back(shapePtr1);
    myShapes.push_back(shapePtr1);
    myShapes.push_back(shapePtr2);
    myShapes.push_back(shapePtr3);
    myShapes.push_back(shapePtr4);

    myShapes.push_back(new Shape);
    myShapes.push_back(new Shape);
    myShapes.push_back(new my2DShape);
    myShapes.push_back(new my3DShape);
    myShapes.push_back(new Triangle);
    /**
     * The above works but I'm looking for a more efficient way
     **/

    while( exit != 1 )
    {
        /**
         * print menu for user
         **/
        cout << "What would you like to do? \n" << endl;
        cout << "1.) Create a shape." << endl;
        cout << "2.) Create a 2D shape." << endl;
        cout << "3.) Create a Triangle." << endl;
        cout << "4.) Quit." << endl;

        /**
         * take input from user
         **/
        cin >> query;

        /**
         * depending on input print menu for chosen shape
         * or set exit to 1
         **/
        switch(query)
        {

            case 1:
            case 2:
            case 3:
                myShapes.at(query)->menu();
            break;

            case 4:
                exit = 1;
            break;

            default:
                cout << "Please pick a number between 1-4\n" << endl;
            break;


        }
    }
}


I'll look up the boost library (it covered later in my course) but this I'd first like to solve without it. Thank you for your answers!
wouldn't this make a new Object and not an Object* ? How would I go about if I wanted to do something like that but with pointers?


The type of the expression "new Object" is Object*.

Ah right (I find pointers and memory addresses a bit hard to understand). I tried to declare and populate the vector like this:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
    vector<Shape*> myShapes;

    myShapes.push_back(new Shape);
    myShapes.push_back(new Shape);
    myShapes.push_back(new my2DShape);
    myShapes.push_back(new my3DShape);
    myShapes.push_back(new Triangle);

    // ...
    // some code
    // ...

    for(int i=0; i < myShapes.size(); i++)
    {
        delete myShapes.at(i);
    }


Is this correct? Is the dynamically created objects deleted and no memory leaks?

I find this delete and new to be very abstract for some reason, when I use delete (or rather when it's executed) this is when the object's destructor is called? And if I don't use delete the memory this object (created by 'new') occupy will not be returned until the program is fully executed?
Last edited on
Think of a pointer as just another variable that happens to contain a value that
magically "points to" another variable.

Your code above is completely correct with no memory leaks.

If you are familiar with malloc and free, then you can think of "new" as "malloc +
runs the constructor" and "delete" as "free + runs the destructor".

For modern OSes that understand virtual memory, if you don't release the memory
the kernel will release it upon program exit. For older OSes such as DOS, if you
forget to release memory, then the memory remains allocated even after the
program exits.

That is a good way of thinking about it, I feel. (Still probably need to read about it a little more though). Thank you for that explanation and all the help jsmith (and firedraco too of course)!
Last edited on
Topic archived. No new replies allowed.