2016-07-06 282 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)?