List vs Vector with Abstract Classes

2019-08-18 11:09发布

问题:

Warning : question from someone inexperienced :)

Hi,

I'm making a mock-up of space invaders for a homework assignment and I'm working on the bullets that the ship and aliens will fire/drop. I have an abstract base class to handle all bullets, with two deriving classes -- missile and bomb.

I originally used a vector, but I read somewhere that a list would be more efficient as they would be added and removed so quickly(?). However, I'm new to lists and I'm having a bit of trouble with it. To be honest, I'm not entirely sure how or if I can use a list with an abstract class at all.

I haven't implemented the bomb class yet because I want to get the missile class working first.

Here's the header of the base class (shot) + missile as an example:

enum attackType { BOMB, MISSILE };

class shot
{
private:
    float xPos,
          yPos;
    attackType bombOrMissile;
public:
    shot(Vector2f pos, attackType b_OR_m);     // passed ship pos + who fired shot
    virtual void draw(RenderWindow & win) = 0; // draws bullet on screen
    virtual Sprite & getSprite() = 0;          // gives sprite information

};

class missile : public shot
{
private:
    Sprite missileSprite;
public:
    missile(Vector2f pos, Texture & t);
    void draw(RenderWindow & win);
    Sprite & getSprite();
};

I have a "Shot manager" class that controls the list of bullets. It increments/decrements the list and changes the sprite position.

Header :

class shotMgr
{
private:
    list<shot*> shotsFired;
    Texture missileTexture;
public:
    shotMgr(); // loads texture
    void shoot(attackType b_OR_m, Vector2f pos);
    void disappear();
    void move();
    void draw(RenderWindow& win);
    int getAmountFilled() { return shotsFired.size(); }
};

my major question is : how can I go about the syntax here? I'm getting myself twisted up trying to work around the ptrs. Is a vector ultimately going to be the better option in this case, or is there just something I'm doing wrong?

Here's one of my shotMgr functions to demonstrate what I'm currently doing (it doesn't compile); the other functions are similar, syntactically :

void shotMgr::disappear()
{
    list<shot>::iterator iter;
    for (iter = shotsFired.begin(); iter != shotsFired.end();)
    {
        if (iter->getSprite().getPosition().y < 0)
        {
            iter = shotsFired.erase(iter);
        }
        else
            iter++;
    }
}

Any advice would be greatly appreciated. Thanks!

回答1:

std::vector is most efficient when you are adding and removing at the end of the collection. When code inserts or removes from anywhere else in the vector, all the elements with an index greater than the element being accessed will incur a "move". That is, when you insert, everything to the right of that element in the array needs to "move over by one". Similarly, when you remove, everything to the right of the element being removed needs to slide over to the left. No different than if you were using an ordinary array as a collection.

std::list is more analogous to a linked list. Might use slightly more memory per element, but is definitely better for random inserts and removals. But the usage of list vs vector isn't the root of your problem.

As for your compile error. It's likely due to this:

list<shot>::iterator iter;

You are declaring an iterator for a list<shot>::iterator, but your collection is of type list<shot*>. So you probably want list<shot*>::iterator. Let's fixup your function. auto to the rescue so you don't have to think about this stuff too hard.

void shotMgr::disappear()
{
    for (auto iter = shotsFired.begin(); iter != shotsFired.end();)
    {
        shot* ptrShot = *iter;

        if (ptrShot->getSprite().getPosition().y < 0)
        {
            iter = shotsFired.erase(iter);
        }
        else
        {
            iter++;
        }
    }
}