2012-03-05 33 views
5

Necesito una aclaración en C++ linux.Puntero como miembro o Referencia como miembro

Tengo class C1 y otro class C2. C1 tendrá la referencia de C2.

class C1 
{ 

    C2 &obj ; 

} 

estoy pensando en dos opciones aquí,

  1. Directamente contiene la referencia de C2 como C2 &obj;
  2. Creación del puntero de C2, como c2* obj;

Lo cual es bueno? ¿Cuál es la diferencia en eso? cuando eliges?

+1

Pregunta similar http://stackoverflow.com/questions/892133/should-i-prefer-pointers-or-references-in-member-data –

Respuesta

3

Evite utilizar un miembro de referencia tanto como sea posible.

Las mismas diferencias que el de las referencias y punteros se aplican aquí,
Si usted tiene un miembro de referencia, entonces debe ser inicializado en el momento de la creación del objeto de clase no se puede tener una inicialización lenta como en el caso de miembro del puntero porque las referencias no pueden ser NULL y no pueden volverse a colocar, mientras que un miembro del puntero puede hacer que apunte a una instancia de C2 de forma perezosa cuando sea necesario.

Además, tenga en cuenta que hay otros efectos secundarios, así, una vez que un miembro de referencia que el compilador no generará el operador de asignación de copia (=) & Usted tendrá que proporcionar uno usted mismo, Es cubersome para determinar qué acción su operador = tomará en tal caso.

a efectos prácticos (a menos que esté realmente interesado del uso de memoria alta debido al tamaño C2) sólo la celebración de una instancia de C2 como miembro del C1 debería ser suficiente, en lugar de puntero o miembro de referencia, que le ahorra un montón de preocupándose por otros problemas que los miembros de referencia/puntero traen consigo a expensas del uso de memoria adicional.

Si debe, utilice un puntero, asegúrese de utilizar un puntero inteligente en lugar de un puntero sin formato, que haría su vida mucho más fácil con los punteros.

+0

Por las razones exactas que mencionaste, usar un puntero es preferible a usar un referencia como miembro Usar una referencia es una solución menos general y puede dar como resultado un comportamiento sorprendente. Sugeriría evitar siempre usar una referencia como miembro. –

+0

Agregaría que hay casos en los que las limitaciones de una referencia se ajustan exactamente a lo que intenta describir con su código, es decir, un objeto asociado a otro objeto durante toda su vida útil (como un objeto de exclusión mutua con mutex objeto, por ejemplo). En tales casos, usar una referencia es más explícito. – Kos

0

un puntero tiene dos ventajas principales para las referencias. el puntero puede ser nulo y un puntero puede moverse (con el operador ++ por ejemplo). El movimiento no lo ayuda aquí. Si su clase C2 no se conoce al crear instancias C1, debe usar un puntero porque no tiene forma de inicializar la referencia, pero el puntero puede inicializarse en nulo.

Como Als dijo, también recomendaría usar punteros cuando la instancia de C2 pueda cambiar. Puede utilizar referencias en este caso, pero creo que los punteros son una solución "más limpia".

+3

No es una ventaja que los punteros no tengan que inicializarse. – dangerousdave

0

Ninguno de los dos es bueno. Si tiene cualquier puntero o variable de miembro de referencia que apunta a algo asignado fuera de su clase, lo más probable es que el diseño del programa sea defectuoso de alguna manera.

Uno de los casos se me ocurre dónde está justificado, es cuando se tiene algún tipo de funcionalidad peculiar de recolector de basura externo.(Por ejemplo asignación/desasignación automática del C++ Builder de componentes VCL en el montón).

Otro caso es donde podría ser válido, es cuando estás emulando una estructura C con una clase C++, o cuando escribes una clase privada dentro otra clase.

Pero lo más probable es que la necesidad de señalar algo fuera de la clase provenga de un diseño de programa defectuoso. Me gustaría pensar dos veces por qué mi código necesita hacer esto, y al menos tratar de agregar la mayor precisión posible al puntero, es decir, const *c2 const obj;

Si tiene punteros de miembro peculiares como este, también debe hacerlo es probable que escriba manualmente un constructor de copias, un operador de asignación y un destructor para su clase.

Editar: La justificación de por qué esto es una mala práctica es el concepto llamado private encapsulation, que es una de las piedras angulares del concepto de diseño programa llamado object-oriented design.

+0

"la necesidad de señalar algo fuera de la clase proviene del diseño defectuoso del programa". No estoy de acuerdo, fuertemente. –

+1

¿De verdad quieres decir que cualquier programa que utiliza un gráfico está mal diseñado? Que el uso de punteros para la navegación está mal diseñado? Yo diría casi lo contrario: si asigna algo dentro de la clase, a menudo es más apropiado hacer que el objeto sea un miembro. Los punteros están reservados para cosas asignadas fuera de la clase. –

+0

@JamesKanze ¿Qué es un "gráfico"? Eso podría significar cualquier cosa, aunque supongo que te refieres al típico ADT llamado "gráfico". Para ese ejemplo, todos los nodos (vértices) del gráfico deberían asignarse dentro de la clase de gráfico. La clase de nodo puede exponer punteros a la clase de gráfico, si se declara como una subclase privada del gráfico. El usuario no debería tener que preocuparse por punteros sin procesar, sino que debe navegar por el gráfico a través de las funciones de miembro público. – Lundin

0

Cuál va a utilizar, depende de lo que necesita exactamente.

Por ejemplo, puede usar una variable de miembro de referencia si necesita algún tipo de inyección de dependencia. Incluso entonces, puedes usar punteros. Sin embargo, tenga en cuenta que las clases con miembros de referencia generalmente no se pueden copiar.

En la mayoría de los casos, debe usar punteros o variables de miembros de valor.

+2

Las referencias hacen que el objeto no se pueda asignar, pero aún se puede copiar. (Pero estoy de acuerdo con su punto básico: la mayoría de las veces, prefiero los apuntadores a las referencias en los tipos de clase. A menos que el tipo ya no se pueda copiar). –

+0

@JamesKanze Sí. Bien dicho. Mi idea sobre no copiable es que la clase hereda de boost :: noncopyable. En ese caso, tampoco es asignable. Pero entendiste lo que quise decir –

Cuestiones relacionadas