指向矢量的指针不指向

Pointer to a vector doesn't point

本文关键字:指针      更新时间:2023-10-16

我已经尽可能地简化了代码。所以我有两个类:

class EntityManager
{
    public:
        std::shared_ptr<std::vector<Entity> > getEntities()
        {
            return std::make_shared<std::vector<Entity> >(m_entities);
        }
    private:
        std::vector<Entity> m_entities{};
};

class System
{
    public:
        void loadEntities(std::shared_ptr<std::vector<Entity> > entities)
        {
            m_entities = entities;
        }
    private:
        std::shared_ptr<std::vector<Entity> > m_entities;
};

现在基本上我希望系统的m_entities指向实体管理器的m_entities。

我这样做了:

system = System();
system.loadEntities(m_entityManager.getEntities());

但后来我把一个元素推回了 EntityManager 的m_entities向量中,这个元素没有添加到系统的m_entities向量中,这意味着我的指针没有指向。

我的错误在哪里?

谢谢!

你的问题是这一行:return std::make_shared<std::vector<Entity> >(m_entities);

正在发生的事情是shared_ptr管理一个新的std::vectory<Entity>容器,该容器初始化为m_entities的副本。因此,修改shared_ptr中的实例不会修改 EntityManager 类中的数据成员,当然shared_ptr也不会看到对EntityManager::m_entities所做的更改。

std::make_shared不会"使这个东西共享";它"使一个将被共享的东西"。

因此,您不能只是凭空创建一个指向已经存在的东西的共享指针。

您的代码动态分配一个std::vectorm_entities构造并由std::shared_ptr管理的副本。这是这个的简写:

std::vector<Entity>* ptr_to_copy = new std::vector<Entity>(m_entities);
return std::shared_ptr(ptr_to_copy);

目前尚不清楚您要做什么,从代码中(您自己承认)无法实现该目标。但std::shared_ptr在这里似乎不太可能合适。

如果是,则从一开始就动态分配和共享向量;否则,只需按原样返回对向量的引用。

无指针解决方案的黑客示例。

#include <string>
#include <iostream>
#include <vector>
//Hack-sample Entity class
class Entity
{
    public:
        Entity(const char * name): m_name(name)
        {
        }
        void print() // this is stupid in real life. Prefer a << overload
        {
            std::cout << "Hi! I'm " << m_name << "!n"; 
        }
    private:
        std::string m_name;
};
class EntityManager
{
    private:
        std::vector<Entity> m_entities;
    public:
        // hide the fact that a vector is being used to store the entities.
        // you can now swap out the vector for most standard containers without
        // changing any code other than the using and the declaration of m_entities
        using iterator = std::vector<Entity>::iterator;
        EntityManager(): m_entities({"bob", "bill"}) 
                         // just pre-loading a few test entities
        {
            // RAII says you should load the entities from their source here
        }
        // get the first entity. 
        iterator begin()
        {
            return m_entities.begin();
        }
        // get the end of the entity list
        iterator end()
        {
            return m_entities.end();
        }
        // adds an entity
        void addEntity(const Entity & entity)
        {
            m_entities.push_back(entity);
        }
        // removes an entity
        iterator removeEntity(iterator rem)
        {
            return m_entities.erase(rem);
        }
};
class System
{
    public:
        // example method to show System working with EntityManager by printing all of the Entities
        void printEntities()
        {
            for (EntityManager::iterator it = m_entityManager.begin();
                 it != m_entityManager.end();
                 ++it)
            {
                it->print();
            }
        }
        // example method to show System working with EntityManager by adding Entities
        void addMoreEntities()
        {
            m_entityManager.addEntity(Entity("Ted "Theodore" Logan"));
            m_entityManager.addEntity(Entity("Excellent!!!"));
        }
    private:
        EntityManager m_entityManager ;
};
// sample test
int main()
{
    System test;
    test.printEntities();
    test.addMoreEntities();
    test.printEntities();
}

这是一个黑客。这只是一个黑客。

如果要正确执行EntityManager,请参阅编写自己的 STL 容器以获取提示。如果你想要所有的花里胡哨的东西,这项工作相当复杂。根据您使用EntityManager的方式以及Entity管理逻辑的复杂性,您最好丢弃EntityManager,只使用普通的旧std::vector

附录:资源获取是什么意思是初始化(RAII)?