2016-05-22 38 views
0

Entity對象的唯一擁有者 - EntityManager是否應該從unique-owner-collection返回weak_ptr或shared_ptr?

class EntityManager 
{ 
    public: 
    std::weak_ptr<Entity> vs std::shared_ptr<Entity> getEntityByID(int ID) const; 
    private: 
    std::vector<std::shared_ptr<Entity>> entities; 
}; 

Entity是需要在程序中被使用,它被從EntityManager通過使用getEntityByID功能接收。

Entity不應該被存放在程序爲shared_ptr其他地方,因爲EntityManager是唯一的擁有者,但它可以與存儲在許多地方爲weak_ptr

我的問題是,如果,getEntityByID應該返回weak_ptrshared_ptr

我的論點使用weak_ptr的返回值:

  • 正是在getEntityByID函數簽名清楚地表明瞭weak_ptr應該讓實體後使用。

我的論點使用shared_ptr的返回值:

  • weak_ptr反正可以轉換爲shared_ptr,並且可以存儲然後根據在其他地方 shared_ptr。從理論上講,每次使用它都會使用lock函數將其轉換爲shared_ptr。
  • 當使用shared_ptr時,那麼在每個功能中,它只能通過 shared_ptr。在每次使用ptr時都不需要使用lock函數。如果它決定存儲指針 ,那麼它只會將其作爲數據成員複製到weak_ptr。
+0

如果'EntityManager'是唯一的所有者,爲什麼不有'std :: vector '並返回引用? –

+0

你爲什麼使用共享/弱指針?調用者可能會在資源被刪除後嘗試使用指針嗎? – Galik

+4

或向量的唯一指針並返回借來的原始指針。 – Flexo

回答

0

如果像你說的EntityManager是實體的唯一所有者,您應該將實體存儲爲unique_ptr,而不是shared_ptr。在更改爲unique_ptr的向量後,應該從.get()方法返回原始指針。理想情況下,EntityManager可以將Entites作爲對象存儲而不是指針並將參考或常量引用存儲到存儲的對象。

+0

正如我在評論中寫的,Entity可以從EntityManager集合中刪除。對實體的引用仍然可以存在於程序中,就像實體(玩家)可以在其他實體(怪物)上鎖定目標一樣。這就是我使用共享指針和弱指針的原因。 –

+0

如果EntityManager將唯一一個將實體存儲爲shared_ptr並且get將返回weak_ptr,則在刪除EntitieManager中的實體後,所有weak_ptr都將在lock()上失敗。如果您的實施需要weak_ptr,則意味着您的設計不好。 – paweldac

+0

「刪除EntitieManager中的Entity後,所有weak_ptr都將失敗(lock)()」 - 是,以及它在程序中的預測情況。 「如果你的實現需要weak_ptr,那就意味着你的設計很糟糕」 - 假設有Entity(人類)和Rocket(存儲引用來鎖定它的目標) - 例如人類。如果作爲引用(在Rocket中)作爲目標,將使用原始指針或引用,那麼如果Human死亡,則Rocket將存儲對無效對象的引用。如果shared_ptr會被使用,並且人類會死亡,那麼人類就會過早地生活。 –

0

shared_ptr是爲共享所有權。存儲在shared_ptr csnnot中的任何對象都假定它具有確定對象生存期的唯一權利。

即使每個人都存儲weak_ptr,每當他們使用它,他們轉換爲shared_ptr,並在使用它的人都可以嘗試刪除它在中央管理器。這會失敗,因爲存在「臨時」shared_ptr

在一箇中等複雜的情況下,會發生這樣的事情,簡單的測試不會暴露它,導致後來很難推斷錯誤。

您可以使用weak/shared來解決此問題,但僅作爲實現細節:語義必須在智能指針之上執行。這些語義將決定使用的智能指針。

+0

是的,我從未從這方面看過它。我認爲它的「獨特」,因爲只有'EntityManager'應該將其存儲爲shared_ptr,但是。即使函數將其臨時存儲在堆棧上,它也是臨時所有者。 「存儲在shared_ptr csnnot中的任何對象都假定它具有確定對象生存期的唯一權限」 - true。那麼你認爲在這種情況下我應該從getEntityByID函數返回shared_ptr? –

相關問題