2008-10-07 19 views
24

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?¿Por qué no debería usar referencias a punteros inteligentes?

Gracias por aclarar

+0

Es la misma razón por la cual el almacenamiento de referencias a otros tipos de objetos es malo, el objeto puede ser destruido y tendrá una referencia colgante. Se supone que los punteros inteligentes mantienen vivo el objeto al que apuntan, pero no estamos hablando del objeto apuntado, estamos hablando del objeto puntero inteligente en sí mismo. – bames53

+0

Consulte http://stackoverflow.com/questions/327573/c-passing-references-to-boostshared-ptr –

Respuesta

14

Suponiendo que estamos hablando aquí ... shared_ptr

Es ésta simplemente por el uso de la referencia del puntero inteligente después de su sido destruidos?

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á examinar 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 weak_ptr

Las tiendas de plantilla de clase weak_ptr una "referencia débil" a un objeto que eso ya gestionada por un shared_ptr. Para acceder al objeto, un weak_ptr puede ser convertido a shared_ptr utilizando el constructor shared_ptr o el miembro bloqueo de función. Cuando el último shared_ptr al objeto desaparece y se elimina el objeto, el intento de obtener una shared_ptr del weak_ptr casos que se refieren a la objeto eliminado se producirá un error: el constructor se lanzar una excepción de tipo impulso :: bad_weak_ptr y weak_ptr :: lock devolverá shared_ptr vacío.

Tenga en cuenta que el método caducado() también le indicará si su ptr aún está activo.

5

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).

3

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 que un método 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 modifique el valor de un parámetro de puntero inteligente, pasar como referencia es obligatorio, como ocurre con cualquier otro tipo.

1

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 indicador tonto, con todos los riesgos y errores que este último implica.

+0

"_con todos los riesgos y errores que este último implica._" ¿cuáles son? – curiousguy

+0

El más grande en este contexto es la falta de recuento de referencias. – JohnMcG

0

Hemos hecho a medida smartpointers y siempre hacer un hábito de pasar una 'refsomething const &'

no aumentar o disminuir el puntero inteligente, y como tal - y lo más importante - llamadas a InterlockedIncrement/Se evitan los decrementos que a su vez evitan un memory fence y todas las cosas que van con eso: bloqueo de bus, invalidación de caché, ...

+0

La función "Interbloqueada" no ** causa ** la invalidación de la memoria caché. – curiousguy

+0

Tienes razón. Estaba equivocado. No habría invalidación de caché ni bloqueo de bus de memoria en este caso. Sin embargo, si hay varios hilos que acceden a este recuento, la cantidad de ciclos perdidos dentro de las funciones Enclavadas ... es bastante no determinista y puede ser bastante alta. El efecto podría ser incluso peor que un caché en la papelera. Entonces hay buenas razones para evitarlos. – QBziZ

0

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 utiliza una referencia con un modificador const en lo que se refiere a continuación, usted tiene una inteligente referencia observación:

const smart_ptr<T>& 

Es interesante y útil, la const le impide utilizar la referencia decir, nulo 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 una tarea que requiere todo tipo de problemas.

Cuestiones relacionadas