2012-09-12 56 views
2

我在C++中編寫了一個相對較大的項目,並且存在對象刪除問題。該項目,準確地說是一個roguelike遊戲。C++安全對象刪除

我有一個類Npc這是遊戲中的每個怪物。它們被創建並存儲在一個單獨的類Storage<Npc>中,負責其管理(加載,保存,創建,刪除等)。每當怪物死亡時,相應的對象npc必須完全刪除並銷燬。刪除對象本身並不是一個問題,我只需要調用Storage<NPC>中的一個方法。問題是代碼中包含了很多指向這個已經死亡的npc的指針,現在這些指針是無效的,並且試圖使用它們會導致很多問題。例如:

  1. 在他去世前可能會有一個他打算執行的操作。
  2. 他在其上放置唱片的瓷磚上有一個指向他的指針。
  3. 他可能參與過一些連續的活動,比如擒拿某人。

代碼中有很多這樣的指針,所以幾乎不可能簡單地跟蹤它們。我需要的是確定一個npc已經死亡的方法,並且該地址上沒有存儲實際的對象,所以仍然有這個指針的代碼部分可以充分地對他的死亡作出反應。

我自己也想出了一些想法,但至今沒有人似乎真的對我好:

  • 我可以問Storage<NPC>類,如果有這種地址的對象。潛在的問題是,刪除對象後,可能會在同一地址分配另一個對象,這會導致錯誤。
  • 我可以通知所有可能使用無效指針的位置。這是一個壞主意,因爲這些地點的數量會隨着時間的推移而增加,這樣做是一種痛苦。
  • 我可以實現一些版本的智能指針,但我不確定要使用哪一個。

TL;博士版本:我需要一個解決方案,如果一個指針指向會告訴我一個對象,或者它指向的內存空閒塊,或者一些其他的對象,原來的對象刪除後分配。

+0

每當內存被釋放/變得無效時,如何將它設置爲'nullptr'? :P – SingerOfTheFall

+0

您已經用答案標記了您的問題:使用智能指針。我建議使用std :: shared_ptr – stefan

+0

@SingerOfTheFall,我猜你想說的是,每當我做'刪除pnpc;'我應該'pnpc = 0;'。但是,如果有另一個指針等於'pnpc'被存儲在程序中的其他地方,它不會被設置爲0,所以我猜這是行不通的。 – Saage

回答

2

如何使用弱指針?如果將Npc存儲在std::shared_ptr(C++ 11,對於C++ 03使用std::tr1::shared_ptr)中,則可以創建std::weak_ptr(對於C++ 03,再次使用std::tr1::weak_ptr),其中引用shared_ptr。當shared_ptr實際上刪除它的對象時,那麼所有的weak_ptrs都能夠解決這個問題。

雖然我不得不想知道爲什麼你要刪除Npc s,這些s仍然在其他地方使用(例如仍然有動作)。如果不是試圖讓所有這些其他參考文獻發現您已刪除Npc,則只需要Npc在所有參考消失後死亡,然後單獨使用shared_ptr(無weak_ptr)將正常工作。

+0

我想用我描述的方法,因爲這就是遊戲機制的工作原理。 NPC隨時可能死亡,而且他不能再執行任何動作或成爲地圖的一部分,這是非常有意義的。我不想在NPC死後執行任何有意義的代碼,並且確保在他死後立即刪除相應的對象。 – Saage

+0

@Saage:我想如果一個Npc死了,那麼你會主動刪除它的動畫,並在刪除Npc之前刪除其在地圖上的存在(或者可能作爲其銷燬的一部分,儘管這可能是一個壞主意),而不是依靠地圖和動作列表來實現後來的Npc消失。通過這種方式,您可以執行諸如查詢動作列表的大小,並確保實際上是待處理動作的計數。 –

3

根據您提供的信息,我可以建議您實施Observer Pattern。 如果有需要對NPC的死亡作出反應的代碼,這種模式是可行的。具有NPC指針參考的代碼部分將在NPC死亡時通知他們,並刪除指向NPC的指針副本,並對NPC的死亡作出反應(無論如何需要)。在NPC被刪除之前,死亡通知會發送給所有observers

通過這種模式,您可以實施諸如「英雄每殺死一個怪物獲得50 HP」等機制,並且它很容易擴展。

如果沒有代碼需要積極響應NPC的死亡,並且只需要處理NPC死亡的情況,那麼您也可以使用Kevin Ballard的建議使用shared_ptr

+0

我想我最終會使用'shared_ptr',因爲它聽起來更簡單,但觀察者模式是一個好主意,我一定會覺得它很有用,謝謝! – Saage

0

一種選擇是在你的班級中包含一個引用計數。當某個其他對象(例如一個房間)要持有一個指向npc的指針時,該房間有責任增加npc的引用計數。現在,不是隻是刪除一個死的npc,而是將它標記爲已死(如果您還沒有正確的標記,則通過另一個新的數據成員),並且只有在其引用計數爲零時纔會刪除。房間對象還有責任定期檢查該標誌,並且如果它瞭解到npc已經死亡,它會減少其參考計數(如果計數現在爲零,將導致死後刪除)。