2016-07-06 168 views
0

我尽可能简化了代码。 所以我有两个类:指向矢量的指针不指向

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载体和系统的m_entities载体不添加这个元素,这意味着我的指针不指向。

我的错误在哪里?

谢谢!

+1

简单的代码很好,但它仍然必须是完整的。再次阅读如何构建[MCVE]。 –

+3

不要以为你需要一个共享指针。 'EntityManager'是实体列表的显而易见的所有者,它看起来像'System'拥有'EntityManager'。所有的所有权和生命期应该是已知的。 – user4581301

+0

你应该知道什么意思?你有什么建议使用? – Urefeu

回答

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所做的更改。

+0

谢谢。有没有办法使用shared_ptr来解决它? – Urefeu

+0

@Urefeu是的,但没有意义。你不需要共享指针。 – user4581301

+0

@Urefeu为什么对shared_ptr的痴迷在这里? –

2

std::make_shared没有“让这个东西分享”;它“会让事情分享”。

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

你的代码中动态分配std::vector复制从m_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似乎不太适合。

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

+0

然后,我对使用不同的指针有点遗憾。我应该何时使用原始的,共享的,独特的...? – Urefeu

+0

@Urefeu研究关于同一主题的其他问题,然后可能会问一个_new问题_。 –

+0

@Urefeu涵盖在这里:http://stackoverflow.com/questions/8706192/which-kind-of-pointer-do-i-use-when自这篇文章后,名称已经稍微改变,但逻辑仍然成立。 – user4581301

0

一个无指针解决方案的例子。

#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)?