# std::vector question...

This topic is 4735 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

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 on other sites
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 on other sites
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 on other sites
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 on other sites
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 on other sites
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 RussellJust 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).

##### Share on other sites
Quote:
 Original post by snk_kidi'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 on other sites
Quote:
 Original post by snk_kidi'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:

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 on other sites
Your push back will look like this;

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 on other sites
Quote:
Quote:
 Original post by snk_kidi'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:

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.

• 17
• 10
• 19
• 14
• 19