c++ - shared_ptr - ¿Por qué no debería usar referencias a punteros inteligentes?
smart pointer c++ (6)
Recuerdo leer en alguna parte que el uso de referencias a punteros inteligentes puede causar daños en la memoria. ¿Esto se debe simplemente al uso de la referencia del puntero inteligente después de su destrucción? ¿O el recuento de referencias se estropea?
Gracias por aclararlo
Cuando se utilizan punteros inteligentes (o cualquier objeto de gestión de asignación) se cuenta con los comportamientos definidos en el constructor / destructor para gestionar refs / derefs / locks / unlocks. Como resultado, esos tipos de objetos deben ser objetos verdaderos para funcionar correctamente. cuando se utilizan referencias a tales objetos (o punteros) se está pasando por alto el mecanismo (y pidiendo un wedgie).
La parte "inteligente" de los punteros inteligentes es administrada por los constructores, destructores, operadores de asignación y otras funciones de la clase de puntero inteligente. Al usar una referencia, está eludiendo estas operaciones: no se llamará al constructor cuando se inicialice su referencia, y no se llamará al destructor cuando su referencia quede fuera del alcance.
En esencia, una referencia a un puntero inteligente es un puntero tonto, con todos los riesgos y trampas que este último implica.
Todavía hay muchos casos en los que una referencia a un puntero inteligente es una buena idea. Un ejemplo obvio es el método de asignación de la clase de puntero inteligente, que acepta una referencia a otro puntero inteligente como su parámetro.
Hacer un método que acepte una referencia de puntero inteligente significa que el parámetro no incrementa la cuenta de referencia interna del puntero inteligente. Esto puede mejorar el rendimiento, pero probablemente no mucho. Además, hay muchas cosas que el método no puede hacer con la referencia, o con el puntero inteligente original. Si sabes lo que son estas cosas y las evitas, pasar por referencia funciona muy bien. Por supuesto, el propósito de los indicadores inteligentes es evitar tener que saber estas cosas.
Además, si tiene un método que modificará el valor de un parámetro de puntero inteligente, se requiere pasar como referencia, como ocurre con cualquier otro tipo.
Asumiendo que estás hablando de shared_ptr aquí ...
¿Esto se debe simplemente al uso de la referencia del puntero inteligente después de su destrucción?
Esta es una buena respuesta. Es posible que no sepa absolutamente la vida útil del puntero a la que se refiere su referencia también.
Para evitar esto, querrá ver boost :: weak_ptr. No participa en el recuento de referencias. Cuando necesitas usarlo, te da un shared_ptr que desaparece una vez que hayas terminado con él. También le permitirá saber cuándo se ha recopilado el puntero al referido.
De la documentación de weak_ptr
La plantilla de la clase weak_ptr almacena una "referencia débil" para un objeto que ya está administrado por un shared_ptr. Para acceder al objeto, un weak_ptr se puede convertir a un shared_ptr utilizando el constructor shared_ptr o el bloqueo de función miembro. Cuando el último shared_ptr del objeto desaparece y el objeto se elimina, el intento de obtener un shared_ptr de las instancias weak_ptr que hacen referencia al objeto eliminado fallará: el constructor arrojará una excepción de tipo boost :: bad_weak_ptr, y weak_ptr: : lock devolverá un shared_ptr vacío.
Tenga en cuenta que el método caducado () también le indicará si su ptr aún está activo.
Tenemos smartpointers personalizados y siempre tenemos el hábito de pasar un ''const refsomething &''
no incrementa ni disminuye el puntero inteligente, y como tal, y lo que es más importante, evita las llamadas a InterLockedIncrement / Decrement, lo que a su vez evita una valla de memoria y todo lo demás: bloqueo de bus, invalidación de caché, ... .
Pasar una referencia a un puntero inteligente a una función es perfectamente seguro y es una buena idea. El objeto puede desaparecer, pero el puntero inteligente no lo hará, estará ahí sentado diciendo nulo al menos hasta que la función regrese. Es la mejor manera de alias de un puntero inteligente dentro de su alcance. Si usa una referencia con un modificador const a lo que se refiere, entonces tiene una referencia de observación inteligente:
const smart_ptr<T>&
De manera interesante y útil, el const le impide usar la referencia para decir, anular el puntero inteligente y eliminar el objeto, pero no impide que el puntero inteligente original se anule y su referencia reflejará ese cambio.
Devolver una referencia al puntero inteligente de una función es pedir todo tipo de problemas.