2011-11-09 21 views
5

Dada una clase "A" existe y es correcta. ¿Cuáles serían algunos de los resultados negativos de usar una referencia a "A" en lugar de un puntero en una clase "B"? Es decir:¿Cuáles son algunas de las desventajas de usar una referencia en lugar de un puntero?

// In Declaration File 
class A; 

class B 
{ 
public: 
    B(); 
    ~B(); 
private: 
    A& a; 
}; 

// In Definition File 
B::B(): a(* new A()) 
{} 

B::~B() 
{ 
    delete &a; 
} 

Se omite código adicional para su posterior corrección de "B", tales como el operador constructor de copia y asignación, sólo quería demostrar el concepto de la cuestión.

+1

Interesante. No he visto ese código antes. Puede ser, esta es solo una forma de evitar la desreferenciación y el uso de '->' y aún hacer 'a' dinámicamente asignado, por alguna razón:? +1 para la pregunta. –

+0

¿Cuál es el punto de esto, en lugar de simplemente 'A a;'? ¿No sería eso mejor que ambas referencias o punteros? – tenfour

+1

@tenfour en muchos casos, pero es un ejemplo simplificado: supongamos que el valor detrás de 'a' es creado por una fábrica. – justin

Respuesta

4

Las limitaciones inmediatos son que:

  • No se puede alterar el valor de una referencia. Puede modificar el A al que hace referencia, pero no puede reasignar o reasignar a durante la vida útil de B.
  • a nunca debe ser 0.

Así:

  • El objeto no es asignable.
  • B no debe ser copiable, a menos que enseñe A y sus subtipos para clonar correctamente.
  • B no será un buen candidato como un elemento de los tipos de colecciones si se almacena como valor. Un vector de B s probablemente se implementará más fácilmente como std::vector<B*>, lo que puede presentar más complicaciones (o simplificaciones, según su diseño).

Estas pueden ser cosas buenas, según sus necesidades.

Advertencias:

  • corte es otro problema a ser consciente de sia es asignable y asignación se puede llegar en B.
+1

+1 para "estas pueden ser cosas buenas" ... que es lo que creo que son (suponiendo que sean aplicables). Usar una referencia en lugar de un puntero cuando sea posible documenta el hecho de que no es nulo y no cambiará ... información muy útil al tratar de darle sentido al código de otra persona. – timday

+0

Editado para reflejar que el código que faltaba era el constructor de copias y el operador de asignación. – JadziaMD

+1

Ese primer "inconveniente" es "algo muy, muy, bueno", y el segundo simplemente lo extiende. Que 'B' ya no se pueda asignar también es bueno, porque es mejor que 'B' sea asignable de una manera discontinua. –

1

Por supuesto, al agregar un miembro de referencia a su clase B, significa que el compilador ya no puede generar los constructores implícitos por defecto y de copia, y los operadores de asignación; y ni un operador de asignación escrito manualmente puede reasignar a.

No creo que haya resultados negativos, aparte del hecho de que delete &a puede parecer extraño. El hecho de que el objeto fue creado por new se pierde un poco al vincular el resultado a una referencia, y puede ser importante ya que el hecho de que su vida útil debe ser controlada por B no está claro.

1

Si utiliza una referencia:

  • Debe proporcionar el valor en el tiempo de construcción
  • no se puede cambiar lo que se refiere a
  • No puede ser nulo
  • Se evitará que su clase de ser asignable

Tal vez debas considerar el uso de una p inteligente ointer de algún tipo en su lugar (std :: unique_ptr, std :: shared_ptr, etc.). Esto tiene el beneficio adicional de eliminar automáticamente el objeto por usted.

2

No se puede cambiar el objeto al que se hace referencia después de un hecho, p. en asignamiento. Además, hace que su tipo no sea POD (el tipo proporcionado no sería POD de todos modos debido al miembro de datos privados, pero en algunos casos podría importar).

Pero la principal desventaja es que probablemente pueda confundir a los lectores de su código.

0

Una referencia a un objeto dinámicamente asignado viola el principio de menor sorpresa; es decir, nadie espera que el código se escriba como lo hizo. En general, eso hará que el costo de mantenimiento sea más alto en el futuro.

Cuestiones relacionadas