Sign in to follow this  
OldJames

Vector of Objects

Recommended Posts

I'm looking to implement vectors to manage objects for a game. Has anyone stumbled across a bit of a tutorial on doing this properly? I haven't had much luck, so I hacked it to use arrays, but it's certainly not the route I want to go. I'm writing a missile command type clone using Allegro and C++. I figured the best way to go about it is have each missile be a stand alone object, and use vectors to destroy the object on collision, and pop in new missile objects when needed. Any thoughts or help appreciated. More Specifically: -The Missile object constructs with a pointer to a Bitmap buffer, as it handles it's own drawing. -I think something like vector<Missile> vMissiles; vMissiles.push_back(Missile(buffer)); [Edited by - OldJames on March 12, 2009 9:23:40 PM]

Share this post


Link to post
Share on other sites
Here you go!

Hope this helps!

Furthermore, If you want to add objects with non-default construction to a vector you can do so like this:


std::vector<missile> myMissiles(5, missile(buffer));



This will create a vector of 5 missle's constructed with buffer. In the case that you want to use push_back you would need to create the object first then add it to the vector:


std::vector<missile> vMissiles;

missile aMissile(image);
myMisiiles.push_back(aMissile);



Note: vMissiles will make a copy of aMissile in this circumstance.

Share this post


Link to post
Share on other sites
It's rather inefficient were there to be a large quantity of objects contained in the vector but I've had been doing something like this:


class Object{
//stuff
}

std::vector<Object*> missile_container;

void spawn_function(){
if we need a missle{
Object *missle = new Object();
missile_container.push_back(missile);
delete missle; //just to make sure the new has a matching delete...
}




Needless to say, that example won't compile. It's just to demonstrate the idea ;)

I'm playing with a new way of handling my objects right now though.

Share this post


Link to post
Share on other sites
Vectors are pretty simple. They're just arrays that can resize themselves so you don't have to worry about it, and you can access much like an array (myVector[index]), and even know how much they hold (myVector.size()). Livengood gave you a good reference! [lol]

~Jonathan

Share this post


Link to post
Share on other sites
You do have to keep in mind that objects that are put into vectors need to be copy-constructible and assignable. A vector may copy around some objects when it's resizing itself, and you don't want your objects to break because of that (which isn't a problem for plain data objects, but once your objects start allocating and owning things, you'd better make sure your copy constructor, assignment operator and destructor take care of things properly).

For more complex objects, I usually store pointers to them in a vector, not the objects themselves. Recently I started using smart pointers instead, as to automate the memory management again.


@caldiar: your example is flawed: you're deleting the missile object that you created right after you added a pointer to it in the vector. The pointer gets copied, the object it's referring to does not, so you're essentially storing invalid pointers in your vector. You should only delete an object right before you remove it's pointer from the vector.

Well, that's why I moved on to smart pointers. ;)

Share this post


Link to post
Share on other sites
Are we all agreeing that Vectors are the best way to go? Or is it over complicating what I'm trying to achieve?

I'm having a hard time finding a tutorial on implementing vectors in this way, although I'm sure it's pretty common practice.

Share this post


Link to post
Share on other sites
Quote:
Original post by caldiar
It's rather inefficient were there to be a large quantity of objects contained in the vector but I've had been doing something like this:

*** Source Snippet Removed ***

Needless to say, that example won't compile. It's just to demonstrate the idea ;)

I'm playing with a new way of handling my objects right now though.

Even on pseude-code level, what your code does is allocate new missile, push it in vector, and delete it, causing missile_container to contain only garbage.

Also, I guess your claim for the inefficiency is about large amounts of push_back() calls, and allocations caused by that. std::vector has member function reserve(), which you can call if you have an idea how large quantity it should contain.

Quote:
Are we all agreeing that Vectors are the best way to go?

When you want to delete missiles from middle of container, I'd suggest std::list<Missile> container.

Share this post


Link to post
Share on other sites
Mmm, yes the delete was mentioned before. I threw it in as an afterthought so people wouldn't point out what would then be a memory leak :)

I had overlooked the fact that the pointers would be invalid after a delete :D

Share this post


Link to post
Share on other sites
To wrap up, I went with a list per @Ftn

I found the following useful:
http://www.yolinux.com/TUTORIALS/LinuxTutorialC++STL.html

Share this post


Link to post
Share on other sites
Quote:
Original post by Captain P

@caldiar: your example is flawed: you're deleting the missile object that you created right after you added a pointer to it in the vector. The pointer gets copied, the object it's referring to does not, so you're essentially storing invalid pointers in your vector. You should only delete an object right before you remove it's pointer from the vector.


Correct, for the example to make sense, this code should be as follows:


Object *missle = new Object();
missile_container.push_back(*missile);
delete missle; //just to make sure the new has a matching delete...




Notice that the only thing I changed is adding a * in the second line, therefore adding the object the pointer is pointing to in the vector, instead of the pointer itself.

Anyways, if you tried to do the incorrect example your compiler will probably throw an error saying that you can't convert a pointer to a const, non-pointer datatype, or something of the sort. If missile_container was only meant to store missiles, trying to add pointers to missiles will not make that code compile.

Share this post


Link to post
Share on other sites
Quote:
Original post by JustChris
Correct, for the example to make sense, this code should be as follows:

*** Source Snippet Removed ***

No, that code does not make (much) sense either. The original example worked with a vector of Missile pointers.

And just in case you're working with a vector<Missile>, it doesn't make any sense to dynamically allocate a Missile, add a copy of it to the vector, and then delete the first instance. You should just add a Missile instance to the vector directly.

Share this post


Link to post
Share on other sites
Well, here's what I'm actually doing:

ObjectManager.hpp

class ObjectManager{
public:
ObjectManager();
~ObjectManager();

void SpawnObject();
void DeleteAllObjects();

private:
std::vector<basicObjectType*> object_container; //store classes derived from basicObjectType
}





ObjectManager.cpp

ObjectManager::ObjectManager(){
}
ObjectManager::~ObjectManager(){
DeleteAllObjects();
}

void ObjectManager::SpawnObject(){
derivedObjectType *missile = new derivedObjectType(); //derived from basicObjectType
object_container.push_back(missile);
}

void ObjectManager::DeleteAllObjects(){
int i = 0;
while(i < object_container.size()){
delete object_container[i];
i++;
}
}




This still won't compile because I left out includes for STL files and two classes (basicObjectType and derivedObjectType) aren't defined.

This does work for me though. If there are issues with the example (keep in mind it's kind of pseudo...) please say so.

Share this post


Link to post
Share on other sites
Ok, that example is cool. It's just that your first example gave a wrong impression of when to delete something. It's the beginners section here after all. :)

Share this post


Link to post
Share on other sites
Quote:
Original post by Captain P
No, that code does not make (much) sense either. The original example worked with a vector of Missile pointers.

And just in case you're working with a vector<Missile>, it doesn't make any sense to dynamically allocate a Missile, add a copy of it to the vector, and then delete the first instance. You should just add a Missile instance to the vector directly.


Ah, I see what you mean. I was trying to correct Caldiar's original code while looking at OldJames' missile vector constructor, making my code all mixed up. Oops :P

Share this post


Link to post
Share on other sites
Quote:
Original post by Captain P
Ok, that example is cool. It's just that your first example gave a wrong impression of when to delete something. It's the beginners section here after all. :)


Yeah, sorry about that heh :) I had assumed it would be known to not immediately delete the object like I had shown in my example but I had forgotten this was the beginner's section. Looking back on it, I would have been confused to see that example.

On the second example, I hope I didn't give the wrong impression when I said "please correct this if it's wrong". I just tend to overlook glaring issues and thought there might be something I overlooked.

Share this post


Link to post
Share on other sites
You're not even using smart pointers, so I'm still giving this thread a failing grade [grin]. Honestly, smart pointers only help newbies, not hinder them.

std::vector< boost::shared_ptr<Object> > my_objects;

Done, no worries about memory. I don't really have time to give a grander explanation, so I'll hope somebody else fills in in my stead.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this