He estado aprendiendo punteros administrados últimamente y encontré el siguiente escenario.C++ shared_ptr of stack object
Estoy implementando una clase de modelo/controlador para una vista de juego. Mi punto de vista, representará las cosas en el modelo. Muy claro. En mi función principal, crear instancias de los tres de esta manera:
RenderModel m;
m.AddItem(rect); // rect gets added just fine, it's an "entity" derivee
RenderView v;
v.SetModel(m);
Mi render clase de vista es bastante sencillo:
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;
};
La aplicación de setView es bastante estándar:
void RenderView::SetModel(RenderModel& model)
{
_model.reset(&model);
}
El La clave para esto es que la vista almacena un modelo en un puntero inteligente. Sin embargo, en principio, el modelo se asignó en la pila. Cuando el programa sale, la memoria se elimina dos veces. Esto tiene sentido. Mi comprensión actual me dice que todo lo que se almacena en un smart_ptr (de cualquier tipo) no debería haber sido asignado en la pila.
Después de toda la configuración anterior, mi pregunta es simple: ¿cómo puedo dictar que un parámetro no se haya asignado en la pila? ¿Aceptar un puntero inteligente como parámetro es la única solución? Incluso entonces no podía garantizar que alguien que use mi clase de vista no podía hacer algo incorrecto, tales como:
// 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);
Si la persona que llama crea mal la shared_ptr, supongo que no hay forma de detectar algo como esto? Pregunto simplemente, porque creo que puedo cometer este error otra vez, y no quiero pasar horas re-depurando el problema. Podría dejarme una nota adhesiva en mi monitor hasta que se incinere en mi cabeza ... – Short
Existen algunos 'trucos' conocidos para detectar si un objeto vive en la pila o en el montón, como la comparación de direcciones. Todos estos transmiten el comportamiento indefinido o dependiente de la implementación. Supongo que si es solo para insinuarse, puede funcionar, pero no son una solución real. –
No, si su función toma 'std :: shared_ptr', no hay forma de saber si ese puntero apunta a un objeto válido. Dicho esto, si toma explícitamente un 'std :: shared_ptr', es mucho más difícil equivocarse (el código que construye un' std :: shared_ptr' a partir de una variable local se ve mal a primera vista y es fácil de evitar). –