简体   繁体   English

如何正确使用指针向量?

[英]How to properly use a vector of pointers?

I am making small simulation app, with base class named Entity and children classes named Herbivore and Carnivore. 我正在制作小型仿真应用程序,其基础类名为Entity,子类名为Herbivore和Carnivore。 And since I am using SFML, I need to update them, deal with interactions etc, etc. My first idea was to store them in two different vectors, but that's not the most efficient solution, I guess. 而且由于我使用的是SFML,所以我需要对其进行更新,处理交互等。我的第一个想法是将它们存储在两个不同的向量中,但这并不是最有效的解决方案。

Then I've tried using a little bit of polymorphism, but here is where I've utterly failed. 然后,我尝试使用一点多态性,但是在这里我完全失败了。 I have one vector of pointers to the Entity objects. 我有一个指向Entity对象的指针向量。 Here is its declaration: 这是它的声明:

std::vector<Entity*> entityVector;

While creating new objects, I call function from different class: 创建新对象时,我从不同的类调用函数:

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);
}

Here is how I call that function in main Game class: 这是我在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);
        }

And then I proceed to work on that vector, or at least try to, but it crashes by the first try to read data saved under that pointer. 然后我继续处理该向量,或者至少尝试这样做,但是第一次尝试读取保存在该指针下的数据时,它崩溃了。 Of course, through the painful and long process of debugging I've realised, that I create a new object here, pass its address and then destroy it by leaving this function. 当然,通过我经历的痛苦而漫长的调试过程,我在这里创建了一个新对象,传递了它的地址,然后通过保留此函数将其销毁。 So my question is: how to deal with it, so I can keep all of this sweet polymorphism? 所以我的问题是:如何处理它,以便保留所有这些甜美的多态性?

I've realised, that I create a new object here, pass its address and then destroy it by leaving this function. ”我意识到,我在这里创建一个新的对象,通过它的地址,然后离开这个功能破坏。 So my question is: how to deal with it, so I can keep all of this sweet polymorphism? 所以我的问题是:如何处理它,以便保留所有这些甜美的多态性?

You can have a vector of shared_ptr<Entity> and you can create a new dynamically allocated object with code like make_shared<Herbivore>(sprite, position, m_GameResolution) . 您可以拥有一个shared_ptr<Entity>的向量,并且可以使用诸如make_shared<Herbivore>(sprite, position, m_GameResolution)类的代码创建一个动态分配的新对象。

The shared_ptr instead of a raw pointer like Entity* essentially takes care of cleanup. shared_ptr代替了诸如Entity*之类的原始指针,基本上负责清理工作。 When there are no more shared_ptr s referring to that object, it's automatically destroyed and the memory deallocated. 当不再有指向该对象的shared_ptr ,它会自动销毁并释放内存。 We say that it's owned by the collection of shared_ptr s referring to it. 我们说它是由引用它的shared_ptr的集合拥有的。

The make_shared<Herbivore> instead of eg shared_ptr<Entity>{ new Herbivore{ sprite, position, m_GameResolution } } avoids some inefficiency (an extra dynamic allocation) of the latter, and can also help to avoid Undefined Behavior where you create two or more such objects as actual arguments in a function call. 使用make_shared<Herbivore>而不是shared_ptr<Entity>{ new Herbivore{ sprite, position, m_GameResolution } }可以避免后者的效率低下(额外的动态分配),还可以避免在创建两个或多个时出现未定义行为这样的对象作为函数调用中的实际参数。


Example: 例:

#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;
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM