2010-07-13 24 views
3

我目前正在研究2D遊戲引擎,並且已經閱讀過有關auto_ptr的內容,以及您應該如何將它們放在標準容器中。auto_ptr和容器 - C++

我的引擎具有這樣的結構:

StateManager - 有很多 - >國。

在引擎之外的主體中創建和分配狀態。我希望引擎存儲所有狀態的列表/矢量,以便在命令之間切換它們。

例如:

 
SomeState *test = new SomeState(); 
StateManager->registerState(test); 

Since states die when and only when the application dies, can I use this approach?

 
std::auto_ptr<SomeState> test(new SomeState()); 
StateManager->registerState(test.get());

// Inside StateManager State *activeState; // State manager then maintains a vector std::vector<State*> stateList; // and upon registerState it adds the pointer to the vector void registerState(State *state) { stateList.push_back(test); }

The StateManager should only maintain a vector of pointers to the states, it shouldn't need to take ownership. When I want to change state in the engine, I just change the activeState pointer to point to the desired state which is found in the stateList vector.

Is this a bad approach?

回答

9

爲什麼不使用std :: vector <狀態>而不用擔心存儲指針?這聽起來像狀態列表是固定的,所以任何迭代器都不會在程序的生命週期中失效。

或者,我發現Boost Pointer Container庫對於這類事情很有用。

+2

+1用於Boost指針容器。 – mskfisher 2010-07-13 11:55:10

+0

當使用boost容器時,是否將auto_ptr按原樣傳遞給registerState()並將參數類型更改爲std :: auto_ptr,還是仍然使用.get()函數傳遞它? – John 2010-07-13 12:03:35

+3

您不要在boost :: ptr_vector中使用auto_ptrs。您只需將它交給一個裸指針,並且ptr_vector獲得它的所有權。 – Ferruccio 2010-07-13 12:07:33

3

If there is nothing that precludes it (polymorphism etc.), then I'd just use the simplest approach, namely std::vector<State>activeState仍然可以是指針(或迭代器)。

4

由於StateManager不擁有包含的對象,其包含的類型應該是State *,而不是智能指針。可以在main函數中使用auto_ptr,這與StateManager容器無關。

如果你想擁有負責包含對象生命週期的容器,你可以使用智能指針作爲包含的類型。但是使用auto_ptr對此很危險,因爲它擁有原始所有權算法。在這種容器中使用shared_ptr會更好。

+0

+1因爲在這種情況下無需爲管理智能指針或複製對象付費。普通指針是可以的。 – 2010-07-13 12:11:27

+0

也許你可以/想詳細說明爲什麼使用'auto_ptr'會有危險? (什麼時候是原始所有權問題?) – Kissaki 2011-10-06 07:38:33

1

您在發佈的代碼中使用auto_ptr的方式不起作用。

std::auto_ptr<SomeState> test(new SomeState()); 
StateManager->registerState(test.get()); 

當「試驗」變量超出範圍時,它的析構函數會被調用,這將刪除你只是StateManager註冊的SomeState對象。所以現在你的StateManager保持一個指向已刪除對象的指針,這可能會導致崩潰。相反,您可以使用參考計數器智能指針類型進行研究,例如, boost::shared_ptr

+1

現在,狀態管理器在狀態之前被刪除,因爲狀態和狀態管理器應該同時被銷燬,即使這意味着調用main()中auto_ptr狀態的release() - 對? – John 2010-07-13 11:55:43

+0

我不完全確定你的意思,但如果你說在你發佈的代碼中的測試變量不會在StateManager被刪除之前超出範圍,那麼沒有問題,你的方法應該工作得很好。 – Haakon 2010-07-13 12:06:26

+0

所以,「不工作」是不正確的。相反,由於你提到的潛在問題,它很危險。另一個地方/ var/destroy命令你必須記住,而不是代碼管理你(這是auto_ptr的想法)。 – Kissaki 2011-10-06 07:42:14

0

auto_ptr應該在指定的上下文中管理對象的生存時間。例如()MyObject * pNewObject = new MyObejct;

//做某事 delete pNewObject; }

在上面的函數中,如果// Do Something代碼中發生了一些異常,對象將不會被釋放d,並且您將面臨代碼中的內存泄漏。我們在這種情況下使用Auto_ptrs。

但它不適用於以下上下文(釋放數組)。在auto_ptr的析構函數中,它調用delete ptr;但是對於數組,我們必須調用delete [] ptr;如果使用auto_ptr與陣列,內存泄漏會發生,並導致意外行爲 無效美孚() {

無符號字符* pStream =新無符號字符[大小]; ....

delete [] pStream; }

如果你沒有太多的狀態,它不是那麼貪心的內存我建議使用Singleton對象爲你的狀態類。所以你不必擔心內存管理。狀態管理器可以處理活動狀態和狀態對象,但我認爲在狀態管理器外部初始化狀態對象並在statemanager和其他地方執行其他操作並不是一個好主意。請確保創建和銷燬是統一的

+0

初始化依賴於它們的類之外的對象實際上是(或者至少可以)是一個好主意。用於鬆散耦合和/或依賴注入。 – Kissaki 2011-10-06 07:46:15

+0

另外,在最後一段之前,我並不完全明白你對文本的看法。它也沒有引導或闡述你的觀點(最後一段),也沒有回答這個問題。 – Kissaki 2011-10-06 07:47:03