我最近一直在學習託管指針,並遇到以下情況。堆棧對象的C++ shared_ptr
我正在實現遊戲視圖的模型/控制器類。我的觀點,將在模型中渲染事物。非常直截了當。在我的主要功能,我實例所有三個這樣的:
RenderModel m;
m.AddItem(rect); // rect gets added just fine, it's an "entity" derivee
RenderView v;
v.SetModel(m);
我的渲染視圖類是非常簡單的:
class RenderView
{
public:
explicit RenderView();
~RenderView();
void Update();
void SetModel(RenderModel& model);
private:
// disable
RenderView(const RenderView& other);
RenderView& operator=(const RenderView& other);
// private members
boost::scoped_ptr<RenderModel> _model;
};
爲的setView的實現是非常標準:
void RenderView::SetModel(RenderModel& model)
{
_model.reset(&model);
}
的關鍵是,該視圖將模型存儲在智能指針中。然而,主要的是,模型被分配在堆棧上。程序退出時,內存被刪除兩次。這是有道理的。我目前的理解告訴我,任何存儲在smart_ptr(任何類型)中的東西都不應該分配在堆棧上。
經過上述所有設置後,我的問題很簡單:我如何規定參數未分配到堆棧上?是否接受智能指針作爲參數唯一的解決方案?即使這樣用我的視圖類不能做一些不正確,例如我不能保證別人:
// If I implemented SetModel this way:
void RenderView::SetModel(const std::shared_ptr<RenderModel>& model)
{
_model.reset(&*model);
}
RenderModel m;
RenderView v;
std::shared_ptr<RenderModel> ptr(&m); // create a shared_ptr from a stack-object.
v.SetModel(ptr);
如果調用者誤解了shared_ptr,我認爲沒有辦法來檢測這樣的事情? 我簡單地問,因爲我覺得我可能再犯這個錯誤,我不想花費數小時重新調試問題。我可以在自己的顯示器上留下自己的便條,直到它燒到我的頭上... – Short
有一些已知的'技巧'來檢測對象是否存在於堆棧或堆中,如比較地址。所有這些都會導致未定義的或實現相關的行爲。我想如果只是爲了暗示它可能有用,但它們不是真正的解決方案。 –
不,如果你的函數需要一個'std :: shared_ptr',那麼就無法判斷這個指針是否指向一個有效的對象。也就是說,如果它明確需要一個'std :: shared_ptr',那就很難搞砸了(從本地變量構造一個'std :: shared_ptr'的代碼看起來一見不順,很容易避免)。 –