2012-08-26 11 views
5

En primer lugar, me doy cuenta de que esto contradice completamente el propósito de un shared_ptr. Estoy tratando con un código de biblioteca donde las instancias de un sistema de partículas esperan tener un shared_ptr pasado durante la construcción para establecer la textura utilizada para cada partícula. La cuestión es que ya construí el resto de mi programa de forma tal que mis texturas tienen propiedad concreta (si ese es el término correcto): TextureCache posee todas las texturas. Entonces necesito una forma de trabajar con esta clase ParticleSystem sin permitir que elimine mis texturas. Si tuviera que crear una instancia nueva como ParticleSystem(std::shared_ptr<Texture>&myTexture), intentaría destruir la textura después de su destrucción (que es una operación no deseada e inválida, ya que mis texturas ni siquiera se crean con new).Pasar un objeto a una función esperando shared_ptr sin compartir la propiedad

La manera más limpia que veo alrededor de este problema es algo como esto:

  1. Crear una shared_ptr la celebración de la textura en la función que crea el ParticleSystem.
  2. Luego, con la colocación nueva, reconstruya el shared_ptr en la misma ubicación de memoria que el shared_ptr que acabo de crear. La textura ahora tendrá un recuento de referencias de 2.
  3. Cree el sistema de partículas.
  4. Deje que el shared_ptr quede fuera del alcance. Se llamará a su deconstructor ya que se asignó en la pila, y se reducirá el recuento de referencia solo por 1. Por lo tanto, el recuento de referencia para el objeto siempre será 1 mayor de lo que realmente es, y por lo tanto nunca se destruirá automáticamente.

Creo que esta solución es sólida, pero todavía se siente increíblemente hackosa. ¿Hay una mejor manera de resolver mi problema?

+0

por qué no tener shared_ptrs en la memoria caché de la textura? –

+0

@Vaughn que es factible, pero parece un innecesario nivel adicional de direccionamiento indirecto al seguir los punteros a las texturas en lugar de a las texturas en sí mismas y sería un uso indebido de punteros compartidos semánticamente ya que la caché de texturas sigue siendo responsable de decidir cuándo está bien para liberar la textura, no sería * compartir * propiedad. – Ponkadoodle

Respuesta

4

Si desea pasar un puntero no administrado (que usted mismo maneja) para codificar el puntero inteligente como shared_ptr, puede simplemente desactivar «inteligente» funcionalidad puntero mediante la creación de vacío, pero no nulo shared_ptr a través de aliasing constructor:

Texture* unmanagedPointer = ... 
shared_ptr<Texture> smartPointer(shared_ptr<Texture>(), unmanagedPointer); 

Esta solución es más eficiente y más corto que Deleter a medida que otros sugirieron, ya que ninguna asignación de bloques de control y recuento de referencias va en.

Algunos detalles adicionales se puede encontrar aquí:

What is the difference between an empty and a null std::shared_ptr in C++?

How to avoid big memory allocation with std::make_shared

0

Tienda shared_ptr en usted Caché como Vaughn Cato sugiere. Con el fin de eliminar una textura de la caché cuando nadie lo usa simplemente comprobar si use_count función de los rendimientos shared_ptr1, lo que significa caché es el único propietario

3

Puede crear shared_ptr con custom deleter that does nothing. Esto evitará borrar texturas propiedad de este shared_ptr.

struct null_deleter 
{ 
    void operator()(void const *) const 
    { 
    } 
}; 

shared_ptr<Texture> CreateTexture(Texture* myTexture) 
{ 
    shared_ptr<Texture> pTexture(myTexture, null_deleter()); 
    return pTexture; 
} 
+0

+1 por abuso creativo de eliminador. –

1

shared_ptr le permite suministrar un eliminador personalizado. Por lo tanto, shared_ptr se puede utilizar para la memoria asignada con malloc o cualquier otro esquema de asignación de memoria que esté utilizando, incluso podría usarlo para desbloquear automáticamente un mutex o cerrar un archivo, pero me estoy desviando. Puede crear un shared_ptr con un eliminador de nulos que no haría nada cuando su conteo de referencias llega a 0.

Cuestiones relacionadas