2010-07-09 11 views
7

Tengo una función en la que quiero que se realice una acción de limpieza el 90% del tiempo, pero en el 10% quiero hacer otra acción.¿Hay alguna manera de cambiar la acción de eliminación en una instancia existente de shared_ptr?

¿Hay alguna forma de utilizar un control de alcance estándar como shared_ptr<> para que inicialmente pueda tener una acción de eliminación y luego, en la función, se pueda cambiar la acción de eliminación?

shared_ptr<T> ptr(new T, std::mem_fun_ref(&T::deleteMe)); 
ptr.pn.d = std::mem_fun_ref(&T::queueMe); 
+2

¿Por qué no aplicar sus estrategias de eliminación en su propio eliminador personalizado? – Abhay

+0

Estaba tratando de evitar escribir el eliminador personalizado cuando solo tengo que elegir (actualmente) entre 2 funciones de miembro. –

Respuesta

2

No creo que pueda cambiar el eliminador una vez creado el shared_ptr.

¿Pero por qué harías eso? Generalmente, cuando creas un objeto, sabes inmediatamente cómo debe destruirse. Esto no es probable que cambie.

Si realmente debe hacer algunos tratamientos específicos, aún puede proporcionar un eliminador personalizado que hace cosas especiales dependiendo de la lógica requerida.

+2

Acabo de pensar en un motivo, que es que posiblemente podría querer reemplazar el eliminador con un nuevo eliminador que hace lo que hace el antiguo, * y * algo más (como notificar a un oyente de la destrucción del objeto). Pero estoy bastante seguro de que no es factible, aunque solo sea porque el eliminador está en el bloque de control, entonces ciertamente no podrías reemplazarlo con un eliminador con un tamaño diferente. Entonces, como dices, el potencial para este comportamiento debe estar en el 'shared_ptr' desde el principio. –

+0

El caso de uso en el que puedo pensar es que tiene una biblioteca que devuelve un archivo std :: tr1 :: shared_ptr y desea mover el control a std :: shared_ptr y está seguro de que std :: shared_ptr durará más que std :: tr1 :: shared_ptr. ¿Terrible? Absolutamente. –

2

Hay una razón válida para necesitar cambiar el eliminador. Tome esto, por ejemplo:

int foo(std::shared_ptr<double>& bar) { 
    ... 
    std::shared_ptr<double> p(my_allocator<double>::allocate(), my_deleter<double>()); 
    bar.swap(p); // this copies the deleter 
    ... 
} 

int main(int, char**) { 
    std::shared_ptr<double> d; 
    foo(d); // d now has a new deleter that will be called when it goes out of scope 
    ... 
} 

En este caso la función foo() asigna una doble * utilizando algún asignador especial. Necesita liberar esa memoria de una manera especial también. La persona que llama no debería necesitar saber cómo liberar la memoria.

+0

Nada se cambia aquí. Está creando un nuevo 'std :: shared_ptr', y luego lo usa como cualquier otro objeto de valor. –

+0

@ kuba-ober: Ya veo, he entendido mal su pregunta original. Tienes razón, definitivamente quiere cambiar el eliminador para el puntero administrado después de que se ha construido en lugar de actualizar el eliminador en un objeto shared_ptr existente (como dice el título). –

0

Esto no tiene ningún sentido, ya que hay un número de shared_ptr s que gestiona la propiedad del valor. Tendría que modificarlos todos, y eso no es factible. No olvidemos que un bloque de control es un detalle de implementación, por lo que ir "aha, pero cambiarlo en el bloque de control" no funcionará.

Las acciones de eliminación deben ser controladas por la instancia propiedad de shared_ptr, p.

class C { 
... 
    void (C::action*)() { &C::action1 }; 
    void action1(); 
    void action2(); 
    ~C() { (this->*action)(); } 
}; 

void test() { 
    std::shared_ptr<C> a; 
    a->action = &C::action2; 
    // action2 gets invoked once `a` falls out of scope 
} 
Cuestiones relacionadas