Sign in to follow this  
TaskyZZ

std::vector question...

Recommended Posts

TaskyZZ    122
I have a class and have declared it as a vector: std::vector<clsBullets *> Bullets; The Bullet class takes care of the bullet through it's lifetime. So, my bullet class needs to be able to remove itself. When a bullet hits something I erase it like this: Bullets.erase(Bullets.begin()+iBulletNum); And this happens in the main portion of the program. Now, when the bullet class is updating itself (moving) and it comes to the end of it's life (maximum range), I need it to kill itself. How do I do that? How can I erase an element from the vector while inside the class that is inside the vector? Does this make sense? Thanks for any help!

Share this post


Link to post
Share on other sites
mattd    1078
Assuming you're enumerating over the bullets back out in your main program with something like this:


for(std::vector<clsBullets *>::iterator iter = Bullets.begin(); iter != Bullets.end(); iter++)
// Call move function, moves the bullet and checks for collisions
iter->move();


You can then make move() (or whatever equivalent method does the per-game tick handling) return a bool value: true if the object is to continue to exist, and false if it is dead (requesting to be removed from the list):


std::vector<clsBullets *>::iterator iter = Bullets.begin();
while(iter != Bullets.end())
// Call move function, moves the bullet and checks for collisions
if(!iter->move())
// Erase bullet
iter = Bullets.erase(iter);
else
iter++;


Hope this helps.

Share this post


Link to post
Share on other sites
Andrew Russell    1394
My first suggestion is to use std::list rather than std::vector as your container.


Next, give each bullet object an iterator to itself in the list of bullets. You may also have to give each bullet object a pointer to the actual list of bullets. There are variations on this depending on how you want to do it (for instance, you could search by this pointer, rather than storing iterators). Then have the bullet delete itself using its iterator.

Just be careful, you'll in effect be doing a "delete this;" statement, which is not a particularly safe thing to be doing. As you're not using smart pointers, you will actually have to use a "delete this;" statement right after you remove the bullet from the list by iterator within its own function.

More specificly, once you "delete this;" you must return from your function immediatly (don't have to, but its safest) and never reference any of the object's member data either (as it is invalid).


Another, different method would be to mark bullets as "dead", and remove them on the list's next iteration. (ie: remove them externally).

EDIT: The method matt suggests is a variation on this last method.

Share this post


Link to post
Share on other sites
TaskyZZ    122
I am new to C++ and just learned about vectors a couple days ago. Don't know what std::list is, but I will look into it.

As for the solution, I am implementing what mattd suggested. My draw() function actually moves the bullets then draws them, so I just have it returning true if the bullet has died and then I remove the bullet in the next line of code in the main loop.

Thanks for the help guys.

Share this post


Link to post
Share on other sites
Andrew Russell    1394
I highly recomend you look into std::list. Being able to use all the containers where appropriate is a neccessary programmer skill.

A std::vector is like an array, a std::list is like a linked list. In most code, you should just be able to change "std::vector" to "std::list" and have it work.

Your code in particular, doing "Bullets.begin()+iBulletNum" is random access and won't work for a list. But you really shouldn't be doing that anyway in your situation.


Vector pros:
Faster.
Random access.

Cons:
Iterators become invalid if you change the vector
Very slow to add or remove anything except at the end (and even this can be slow)


List pros:
Insertion and removal are fast
Iterators remain valid when modifying the list

Cons:
Slower
Must access sequentially

Share this post


Link to post
Share on other sites
snk_kid    1312
i'm going ask is there a specific reason why your storing pointers to clsBullets and not the actual clsBullets themselfs, prefer the latter unless you have good reason not too.

Quote:
Original post by Andrew Russell
Just be careful, you'll in effect be doing a "delete this;" statement, which is not a particularly safe thing to be doing. As you're not using smart pointers, you will actually have to use a "delete this;" statement right after you remove the bullet from the list by iterator within its own function.

More specificly, once you "delete this;" you must return from your function immediatly (don't have to, but its safest) and never reference any of the object's member data either (as it is invalid).


If your gonna go down that road you'll have to prevent static allocation otherwise your asking for trouble.

Share this post


Link to post
Share on other sites
TaskyZZ    122
Quote:
Original post by snk_kid
i'm going ask is there a specific reason why your storing pointers to clsBullets and not the actual clsBullets themselfs, prefer the latter unless you have good reason not too.



Mainly, just because I don't know what I am doing. :)

Share this post


Link to post
Share on other sites
TaskyZZ    122
Quote:
Original post by snk_kid
i'm going ask is there a specific reason why your storing pointers to clsBullets and not the actual clsBullets themselfs, prefer the latter unless you have good reason not too.



If I change this:

std::vector <clsBullets *> Bullets;

to this:

std::vector <clsBullets> Bullets;

then when I do this:

Bullets.push_back(new clsBullets(PosX+tmp.x,PosY+tmp.y,Facing,Heading));

I get an error. So, when it is no longer a pointer, how do I add a new one to the vector?

This is the error:

error C2664:
'std::vector<_Ty>::push_back' : cannot convert parameter 1 from 'clsBullets *' to 'const clsBullets &'
with
[
_Ty=clsBullets
]
Reason: cannot convert from 'clsBullets *' to 'const clsBullets'
No constructor could take the source type, or constructor overload resolution was ambiguous

What should my push_back look like?

Share this post


Link to post
Share on other sites
_the_phantom_    11250
Your push back will look like this;

Bullets.push_back(clsBullets(PosX+tmp.x,PosY+tmp.y,Facing,Heading));

When this line is called a tempory clsBullets object is created and then copied into the Bullets vector, the temport is then destoryed and the copy remains in the vector.

Share this post


Link to post
Share on other sites
snk_kid    1312
Quote:
Original post by TaskyZZ
Quote:
Original post by snk_kid
i'm going ask is there a specific reason why your storing pointers to clsBullets and not the actual clsBullets themselfs, prefer the latter unless you have good reason not too.



If I change this:

std::vector <clsBullets *> Bullets;

to this:

std::vector <clsBullets> Bullets;

then when I do this:

Bullets.push_back(new clsBullets(PosX+tmp.x,PosY+tmp.y,Facing,Heading));

I get an error. So, when it is no longer a pointer, how do I add a new one to the vector?

This is the error:

error C2664:
'std::vector<_Ty>::push_back' : cannot convert parameter 1 from 'clsBullets *' to 'const clsBullets &'
with
[
_Ty=clsBullets
]
Reason: cannot convert from 'clsBullets *' to 'const clsBullets'
No constructor could take the source type, or constructor overload resolution was ambiguous

What should my push_back look like?


I'm sorry if sounded offensive earlier, i wasn't trying to be. What i said is not valid in every case but in general its preferred where applicable of-course.

Anyways Example:


#include <vector>

struct clsBullets {

float x, y;

clsBullets(float x_, float y_): x(x_), y(y_) {}

//....

};

int main() {

std::vector<clsBullets> v;

v.push_back(clsBullets(3.0f, 4.3f));

}


here is a very useful reference [wink], its worth spending some time on reading the "Concepts" of the standard library containers & algorithms.

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