如何正确使用指针向量?

时间:2018-01-07 19:50:55

标签: c++ vector sfml

我正在制作小型模拟应用程序,其基类名为Entity,子类名为Herbivore和Carnivore。由于我使用SFML,我需要更新它们,处理交互等等。我的第一个想法是将它们存储在两个不同的向量中,但我认为这不是最有效的解决方案。

然后我尝试使用一点点多态性,但这里是我彻底失败的地方。我有一个指向Entity对象的指针向量。这是它的声明:

std::vector<Entity*> entityVector;

在创建新对象时,我从不同的类调用函数:

void ObjectFactory::createHerbivore(Sprite sprite, Vector2f position, 
std::vector<Entity*> *vector)
{
     Herbivore herbivore(sprite, position, m_GameResolution);
     Entity* p_herbivore = &herbivore;
     vector->push_back(p_herbivore);
}

以下是我在主Game类中调用该函数的方法:

        //Creating new herbivore objects
        if (inputEvent.key.code == Keyboard::H)
        {
            srand((int)time(0) * dt.asMilliseconds() + 1 * 800 * entityVector.size() + 5);
            herbivorePosition.x = rand() % (int)videoResolution.x;
            herbivorePosition.y = rand() % (int)videoResolution.y;
            factory.createHerbivore(herbivoreSprite, herbivorePosition, &entityVector);
            (entityVector.back())->setDangerSprite(dangerSprite);
        }

然后我继续研究那个向量,或者至少尝试一下,但是第一次尝试读取保存在该指针下的数据时崩溃了。当然,通过痛苦而漫长的调试过程我已经意识到,我在这里创建了一个新对象,传递了它的地址然后通过离开这个函数来销毁它。所以我的问题是:如何处理它,所以我可以保留所有这些甜的多态性?

1 个答案:

答案 0 :(得分:2)

  

我意识到,我在这里创建了一个新对象,传递了它的地址,然后通过离开这个函数来销毁它。所以我的问题是:如何处理它,所以我可以保留所有这些甜的多态性?

您可以拥有shared_ptr<Entity>的向量,并且可以使用make_shared<Herbivore>(sprite, position, m_GameResolution)之类的代码创建一个新的动态分配对象。

shared_ptr而不是像Entity*这样的原始指针基本上可以用来清理。当没有更多shared_ptr个引用该对象时,它会被自动销毁并释放内存。我们说shared_ptr的集合指的是拥有

make_shared<Herbivore>代替例如shared_ptr<Entity>{ new Herbivore{ sprite, position, m_GameResolution } }避免了后者的一些低效(额外的动态分配),并且还可以帮助避免未定义的行为,其中您在函数调用中创建两个或更多这样的对象作为实际参数。

示例:

#include <iostream>
#include <typeinfo>     // for typeid
#include <memory>
#include <vector>
using namespace std;

struct Entity { virtual ~Entity(){} };
struct Herbivore: Entity {};
struct Carnivore: Entity {};

auto main() -> int
{
    vector<shared_ptr<Entity>> entities;
    entities.push_back( make_shared<Herbivore>() );
    entities.push_back( make_shared<Herbivore>() );
    entities.push_back( make_shared<Carnivore>() );
    entities.push_back( make_shared<Herbivore>() );

    for( auto p: entities )
    {
        cout << typeid( *p ).name() << endl;
    }
}