В последнее время я изучал управляемые указатели и столкнулся со следующим сценарием.
Я реализую класс модель / контроллер для просмотра игры. На мой взгляд, будет рендерить вещи в модели. Довольно прямо вперед. В своей основной функции я создаю все три экземпляра следующим образом:
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);