views:

353

answers:

4
+1  Q: 

Array of Pointers

How can I get an array of pointers pointing to objects (classes) ?

I need to dynamically allocate space for them and the length of array isn't determined until run-time. Can any one explain and tell me how to define it? and possibly explain them how it works, would be really nice :)

+14  A: 

Use std::vector instead. It's designed to dynamically resize the collection as needed.

#include <vector>
// ...
std::vector<Class*> vec;
vec.push_back(my_class_ptr);
Class* ptr = vec[0];
Mehrdad Afshari
thanks, I'll look into that too
hab
A vector of pointers still has a lot of opportunity to leak if you use STL algorithms on the vector. Try to use a vector of objects rather than pointers when you can.
KJAWolf
@KJAWolf: can you give some examples of an STL algorithm which causes a leak with `std::vector<T*>` ?
Evan Teran
Or a boost::ptr_vector<Class>
Martin York
He said opportunities to leak, not that the algorithms themselves inherently leak. So for example, `std::set_difference` creates aliases for some (but not all) of the pointers in your vector. This provides an excellent opportunity for the programmer to mis-manage resources, and hence create leaks. Enter smart pointers, stage left.
Steve Jessop
+7  A: 

You can do this with a pointer to pointer to your class.

MyClass ** arrayOfMyClass = new MyClass*[arrayLengthAtRuntime];
for (int i=0;i<arrayLengthAtRuntime;++i)
    arrayOfMyClass[i] = new MyClass(); // Create the MyClass here.

// ...
arrayOfMyClass[5]->DoSomething(); // Call a method on your 6th element

Basically, you're creating a pointer to an array of references in memory. The first new allocates this array. The loop allocates each MyClass instance into that array.

This becomes much easier if you're using std::vector or another container that can grow at whim, but the above works if you want to manage the memory yourself.

Reed Copsey
Correct me if I'm wrong (its been a while), but don't forget to call delete[] to release when you're finished.
John MacIntyre
I don't think he showed the code where you'd delete - assuming the lifespan of the array is longer than a single function call.Also, resizing this is a pain. Hence the suggestion for vector / list collection classes.
Kieveli
Will I have to call delete if I use vectors? I'll dynamically allocate memory
hab
Manzoor, only use `delete` when you have used `new`. You won't use `new` to *make* a `vector`, so don't use `delete` to destroy it. If you use `new` to allocate the things you're storing *in* the `vector`, then use `delete` to destroy them.
Rob Kennedy
Why do I have to use pointer-to-pointer?
hab
You want an array of pointers pointing to objects. This requires a pointer to pointer - the first points to the array (in memory), where each element of the array is pointing to your class.
Reed Copsey
@Kievelli: I completely agree - I'd use a vector/list of some form, but I still think it's valuable to understand what's happening behind the scenes, especially with this sort of thing.
Reed Copsey
+2  A: 

I can't edit or comment yet so I have to post it in an answer: What Reed Copsey said, but with one fix. When you access elements of your array of pointers you need to access the members like this:

MyClass ** arrayOfMyClass = new MyClass*[arrayLengthAtRuntime];
for (int i=0;i<arrayLengthAtRuntime;++i)
    arrayOfMyClass[i] = new MyClass(); // Create the MyClass here.

// ...
arrayOfMyClass[5]->DoSomething(); // Call a method on your 6th element

I use this method a lot to implement my own dynamic size arrays (what std::vector is), mostly because I have Not Invented Here syndrome but also because I like to customize them to my particular use.

Daniel Bingham
You have Not Invented Here syndrome for `std::vector`? :O If so, you should really consider writing a C++ compiler too; and probably build your own CPU.
Mehrdad Afshari
Well it's partly because I learned to write my own vectors before I learned about the existence of std::vector, and now it's just habit ;)
Daniel Bingham
+4  A: 

Use boost::ptr_vector and forget both array and pointer headaches:

boost::ptr_vector<animal> vec;
vec.push_back( new animal );
vec[0].eat();

You can add elements dynamically and you don't need to worry about deleting them.

fnieto
If Boost isn't an option (sadly, this seems to be the case wherever I happen to work on C++ code, for some inane reasons), but TR1 is - e.g. you're using a recent g++ version, or VC++2008 SP1, then `std::vector<std::tr1::shared_ptr<animal> >` would also do the trick.
Pavel Minaev