指向矢量的指针不指向

时间:2016-07-06 18:25:23

标签: c++ vector shared-ptr

我尽可能地简化了代码。 所以我有两节课:

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指向EntityManager的m_entities。

我这样做了:

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

但后来我将一个元素推回到EntityManager的m_entities向量中,并且这个元素没有添加到System的m_entities向量中,这意味着我的指针没有指向。

我的错误在哪里?

谢谢!

3 个答案:

答案 0 :(得分:2)

您的问题就在这一行:return std::make_shared<std::vector<Entity> >(m_entities);

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

答案 1 :(得分:2)

std::make_shared不会“让这个东西分享”;它“会让人分享”。

所以,你不能只是指出一个指向已经存在的东西的共享指针。

您的代码会动态分配来自std::vector的{​​{1}},副本构建,并由m_entities管理。这是简写​​:

std::shared_ptr

目前还不清楚你要做什么,从(你自己承认)没有实现这个目标的代码。但std::vector<Entity>* ptr_to_copy = new std::vector<Entity>(m_entities); return std::shared_ptr(ptr_to_copy); 似乎不太适合。

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

答案 2 :(得分:0)

Hack无指针解决方案的示例。

#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权限,请参阅Writing your own STL Container以获取提示。如果你想要所有的花里胡哨,这项工作相当复杂。根据您使用EntityManager的方式以及Entity管理逻辑的复杂程度,您可能最好放弃EntityManager并使用简单的旧版std::vector

附录:What is meant by Resource Acquisition is Initialization (RAII)?