Pregunta

En un proyecto de C ++ que utiliza punteros inteligentes, tales como boost::shared_ptr, lo que es una buena filosofía de diseño relacionadas con la utilización de " this "?

Tenga en cuenta que:

  • Es peligroso para almacenar el puntero prima contenida en cualquier puntero inteligente para su uso posterior. Usted ha dado el control de la eliminación del objeto y confiar en el puntero inteligente de hacerlo en el momento adecuado.

  • Los miembros de la clase no estáticos utilizan intrínsecamente una puntero this. Es un puntero en bruto y que no se puede cambiar.

Si alguna vez this almacenar en otra variable o pasarlo a otra función que potencialmente podría almacenar para más adelante o se unen en una devolución de llamada, estoy creando errores que se introducen cuando alguien decide hacer un puntero compartida a mi clase .

Teniendo en cuenta que, cuando ¿Es apropiado para mí utilizar de forma explícita un puntero this? ¿Hay paradigmas de diseño que pueden prevenir errores relacionados con esto?

¿Fue útil?

Solución

Si bien no tengo una respuesta general o algún idioma, existe boost::enable_shared_from_this . Se le permite obtener un shared_ptr dirigiendo un objeto que ya está gestionado por shared_ptr. Dado que en una función miembro que no tiene ninguna referencia a esas gestión de shared_ptr, enable_shared_ptr no permitirá obtener una instancia shared_ptr y pasa que cuando se necesita pasar el puntero this.

Pero esto no va a resolver el problema de pasar this desde dentro del constructor, ya que en ese tiempo, no hay shared_ptr es la gestión de su objeto todavía.

Otros consejos

Pregunta equivocada

  

En un proyecto de C ++ que utiliza punteros inteligentes

El problema no tiene nada que ver con la realidad punteros inteligentes. Es sólo alrededor de la propiedad.

punteros inteligentes son sólo herramientas

Cambian nada WRT el concepto de propiedad, esp. la necesidad de tener la propiedad bien definida en su programa , el hecho de que la propiedad puede ser transferida de forma voluntaria, pero no puede ser tomada por un cliente.

Usted debe entender que los punteros inteligentes (también cerraduras y otros objetos RAII) representan un valor y un WRT relación de este valor al mismo tiempo. Un shared_ptr es una referencia a un objeto y establece una relación: el objeto no debe ser destruida antes de que este shared_ptr, y cuando esto shared_ptr se destruye, si es el último aliasing este objeto, el objeto debe ser destruido inmediatamente. (unique_ptr puede ser visto como un caso especial de shared_ptr donde hay cero aliasing por definición, por lo que el unique_ptr es siempre el último aliasing un objeto.)

¿Por qué se debe utilizar punteros inteligentes

Se recomienda el uso de punteros inteligentes porque expresan mucho con sólo las variables y funciones declaraciones.

punteros inteligentes sólo pueden expresar un diseño bien definido, que no le quitan la necesidad de definir la propiedad. Por el contrario, la recolección de basura quita la necesidad de definir quién es responsable de la cancelación de asignación de memoria. (Pero no le quitan la necesidad de definir quién es responsable de otros recursos de limpieza.)

Incluso en idiomas basura no recolectada puramente funcional, es necesario hacer una propiedad clara: no desea sobrescribir el valor de un objeto si otros componentes todavía tienen el valor antiguo. Esto es particularmente cierto en Java, donde el concepto de propiedad de la estructura de datos mutables es extremadamente importante en los programas de rosca.

¿Qué hay de punteros primas?

El uso de un puntero prima no significa que no existe la propiedad. Es que no es descrito por una declaración de variables. Puede ser descrito en los comentarios, en los documentos de diseño, etc.

Es por eso que muchos programadores de C ++ consideran que el uso de punteros primas en lugar del puntero inteligente adecuada es inferiores : porque es menos expresiva (He evitado los términos "bueno" y "malo" a propósito). Creo que el núcleo de Linux sería más fácil de leer con algunos objetos de C ++ para expresar relaciones.

Se puede implementar un diseño específico con o sin punteros inteligentes. La aplicación que utiliza puntero inteligente apropiada será considerado superior por muchos programadores de C ++.

Su pregunta real

  

En un proyecto de C ++, lo que es una buena filosofía de diseño relacionadas con la utilización de "esto"?

Eso es muy vaga.

  

Es peligroso para almacenar el puntero prima para su uso posterior.

¿Por qué necesita un puntero para su uso posterior?

  

Usted ha dado el control de la eliminación del objeto y confía en el componente responsable de hacerlo en el momento adecuado.

De hecho, algún componente es responsable de la vida de la variable. No se puede tomar la responsabilidad:. Tiene que ser transferido

  

Si alguna tienda esta en otra variable o pasarlo a otra función que potencialmente podría almacenar para más adelante o se unen en una devolución de llamada, estoy creando errores que se introducen cuando alguien decide usar mi clase.

Obviamente, ya que la persona que llama no se le informa de que la función se oculta un puntero y utilizarlo más adelante sin el control de la persona que llama, que está creando errores.

La solución es, obviamente, ya sea a:

  • responsabilidad transferencia para manejar la vida útil del objeto a la función
  • Asegúrese de que el puntero solamente se guarda y se utiliza bajo el control de la persona que llama

Sólo en el frimer caso, usted podría terminar con un puntero inteligente en la implementación de la clase.

El origen del problema

Creo que su problema es que usted está tratando duro para complicar las cosas utilizando punteros inteligentes. punteros inteligentes son herramientas para hacer las cosas más fácil, no más difícil. Si punteros inteligentes complican su especificación, a continuación, reflexionar sobre el sistema de especificaciones en términos de las cosas más simples.

No intente introducir punteros inteligentes como una solución antes de que usted tiene un problema.

Sólo introducir punteros inteligentes para resolver un problema específico bien definido. Debido a que no describen un problema específico bien definido, no es posible hablar de una solución específica (que implica punteros inteligentes o no).

Un ejemplo de uso correcto es return *this; en funciones como operador ++ () y el operador << ().

Cuando se utiliza una clase puntero inteligente, tienes razón en que es peligroso exponer directamente "this". Hay algunas clases de puntero relacionados con boost::shared_ptr<T> que pueden ser de utilidad:

  • boost::enable_shared_from_this<T>
    • Proporciona la capacidad de tener un objeto devuelve un puntero compartida a sí misma que utiliza los mismos datos de conteo de referencia como un puntero compartido existente al objeto
  • boost::weak_ptr<T>
    • funciona mano a mano con los punteros compartidos, pero no les tengas una referencia al objeto. Si todos los punteros compartidos desaparecen y el objeto es liberado, un puntero débil será capaz de decir que el objeto ya no existe y que volverá NULL en lugar de un puntero a memoria no válida. Puede utilizar punteros débiles para obtener punteros compartidos a un objeto de referencia contado válida.

Ninguno de estos es infalible, por supuesto, pero tendrán al menos hacer que su código sea más estable y segura mientras que proporciona un acceso apropiado y recuento de referencias para sus objetos.

Si es necesario utilizar this, sólo tiene que utilizar explícitamente. punteros inteligentes envuelven sólo los punteros de los objetos de su propiedad - ya sea EXCLUSIVAMENTE (unique_ptr) o de forma compartida (shared_ptr).

personalmente me gusta utilizar el este puntero cuando se accede a las variables miembro de la clase. Por ejemplo:

void foo::bar ()
{
    this->some_var += 7;
}

Es sólo una pregunta inofensiva de estilo. Algunas personas, como él, somepeople NO.

Pero el uso de la este puntero para cualquier otra cosa que pueda causar problemas. Si usted realmente necesita para hacer cosas interesantes con ella, realmente debería reconsiderar su diseño. Una vez vi un código que, en el constructor de una clase, se le asigna el presente puntero a otro puntero almacenado en otro lugar! Eso es una locura, y no puedo nunca pensar en una razón para hacerlo. Todo el código era un lío enorme, por cierto.

Puede decirnos qué es exactamente lo que quiere hacer con el puntero?

Otra opción es usar punteros inteligentes intrusivos, y el cuidado de recuento de referencias dentro del objeto en sí mismo, no los punteros. Esto requiere un poco más de trabajo, pero en realidad es más eficiente y fácil de controlar.

Otra razón para pasar alrededor de esto es que si desea mantener un registro central de todos los objetos. En el constructor, un objeto llama a un método estático del registro con esta. Su útil para diversos publicación / suscripción mecanismos, o cuando no desea que el registro para necesita el conocimiento de qué objetos / clases están en el sistema.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top