Si tengo una clase que tiene muchas variables de miembro int
, float
y enum
, ¿se considera eficiente y/o buena práctica devolverlas como referencias en lugar de copias, y devolver referencias constantes donde no se deben hacer cambios? ¿O hay alguna razón por la que debería devolverlos como copias?¿Es una buena idea devolver siempre las referencias de los getters variables miembro?
Respuesta
No hay motivo para devolver tipos primitivos como int
y float
como referencia, a menos que desee permitir su modificación. Devolverlos por referencia es en realidad menos eficiente porque no ahorra nada (int
sy los punteros suelen tener el mismo tamaño) mientras que la eliminación de referencias realmente agrega sobrecarga.
¡Eso fue útil, gracias! – Jengerer
Tengo una pregunta, sin embargo. ¿Qué se debe considerar una compensación justa para usar un puntero o referencia? Por ejemplo, un doble es 8 bytes, y un puntero a un doble es 4 bytes. ¿Los gastos generales añadidos para desreferenciar superan al tamaño más pequeño? – Jengerer
Sí. Mi regla de oro es devolver tipos primitivos directamente, incluso 'double'. Las clases se devuelven como referencias const, incluso las pequeñas. –
Esto es probablemente una cuestión de estilo o preferencia. Una razón para no devolver referencias es porque está utilizando getters y setters para permitirle cambiar la implementación de esos miembros. Si cambió un miembro privado a otro tipo, o lo eliminó por completo porque puede ser computado, entonces ya no tiene la capacidad de devolver una referencia, ya que no hay nada para referenciar.
Por otro lado, devolver referencias para tipos no triviales (clases compuestas) puede acelerar su código un poco más que hacer una copia, y puede permitir que esos miembros se asignen a través de la referencia devuelta (si lo desea).
Si son referencias constantes, quizás esté bien. Si no son referencias constantes, probablemente no.
En cuanto a la eficiencia, en una máquina de 64 bits, las referencias serán cantidades de 64 bits (punteros disfrazados); int
y float
y enum
serán más pequeños. Si devuelve una referencia, está forzando un nivel de indirección; es menos eficiente.
Por lo tanto, especialmente para los tipos incorporados como valores de retorno, generalmente es mejor devolver el valor en lugar de una referencia.
Gracias por la respuesta, que ayudó! – Jengerer
algunos casos es necesario:
Mira sobrecargado operator[]
para cualquier clase. Por lo general tiene dos versiones. La versión mutante debe devolver una referencia.
int &operator[](int index); // by reference
int operator[](int index) const; // by value
En general, está bien para permitir el acceso a los miembros de la clase de entidades de confianza, por ejemplo, por una clase amigos. En caso de que estas entidades de confianza también necesiten modificar el estado, referencias o indicadores para los miembros de la clase, son las únicas opciones que tiene.
En muchos casos, las referencias generalmente simplifican la sintaxis, por ejemplo, cuando 'v' es el vector STL.
v.at(1) = 2 vs *(v.at(1)) = 2;
Casi, las referencias const son mejores. Para los ints y esos no hay ningún punto porque querrías que se cambien o porque son del mismo tamaño (o casi) como referencia.
Así que sí, es una buena idea. Prefiero otro idioma o piratear mis propias cosas en C++ y permitir que la var sea pública (una vez más es solo mi propio material)
Claro, podría hacerlos públicos, pero algunos de ellos no deberían ser de acceso público, ya que tienen ciertas restricciones por el valor que se les puede dar, por lo que los envuelvo con setters/getters para hacer cumplir esas reglas. ¡Gracias por la respuesta! – Jengerer
@Jenger: para reglas muy simples y autónomas, puede dejar que el sistema de tipos lo ayude. Por ejemplo, en lugar de un campo 'int digit' y un setter que comprueba que los dígitos están entre 0 y 9, puede escribir su propio tipo' digit' que solo tiene los valores de 0 a 9 y luego usar un campo público 'digit' en tu clase, sin un getter y un setter. – fredoverflow
Jengerer: En mi propio código digo que haré eso por todas partes porque es mío y nadie más (nadie tiene que tocarlo). Además, si la clase es trivial, lo haré en el trabajo y, hasta el momento, nadie se ha quejado. Pero realmente no hago C++ en el trabajo –
Esta es una pregunta de rendimiento principalmente, pero desde el punto de vista de la robustez diría es preferible devolver valores en lugar de referencias de referencias. La razón es que incluso las referencias const debilitan la encapsulación.Considere esto:
struct SomeClass
{
std::vector<int> const & SomeInts() const;
void AddAnInt (int i); // Adds an integer to the vector of ints.
private:
std::vector<int> m_someInts;
};
bool ShouldIAddThisInt(int i);
void F (SomeClass & sc)
{
auto someInts = sc.SomeInts();
auto end = someInts.end();
for (auto iter = someInts.begin(); iter != end; ++iter)
{
if (ShouldIAddThisInt(*iter))
{
// oops invalidates the iterators
sc.AddAnInt (*iter);
}
}
}
Así que en caso de que tenga sentido semántico y podemos evitar asignaciones dinámicas excesivas prefiero retorno por valor.
Los captadores son para emisiones de una clase digamos Exhaust Car.emit()
, donde el auto acaba de crear el Exhaust
.
Si usted está obligado a escribir const Seat& Car.get_front_seat()
para tener más tarde sentarse en el Driver
, se nota inmediatamente que algo está mal.
Correcly, prefiero escribir Car.get_in_driver(Driver)
que luego llama directamente al seat.sit_into(Driver)
.
Este segundo método evita fácilmente esas situaciones incómodas cuando get_front_seat
pero la puerta está cerrada y prácticamente empuja el controlador a través de la puerta cerrada. Recuerde, ¡solo ha pedido un asiento! :)
En general: siempre devuelva por el valor (y confíe en la optimización del valor de retorno), o se da cuenta de que es hora de cambiar su diseño.
El fondo: clases fueron creadas para que los datos se pueden acoplar con su funcionalidad de acceso, localización de errores, etc. Por lo tanto nunca son clases de actividad, pero orientados a datos.
Otros errores: en C++ si devuelve algo por const ref, entonces puede olvidar fácilmente que es solo una referencia y una vez que su objeto se destruye puede quedar con una referencia no válida. De lo contrario, ese objeto se copiará una vez que abandona el getter de todos modos. Pero el compilador evita las copias innecesarias, ver Return Value Optimization.
- 1. ¿Es una buena práctica proteger las variables miembro?
- 2. ¿Es una buena idea devolver "const char *" de una función?
- 3. Android: ¿es eficiente almacenar referencias a Vistas como variables miembro?
- 4. sqlite e hibernate - es una buena idea?
- 5. ¿Cuándo es una buena idea devolver un puntero a una estructura?
- 6. ¿Campos multivalorados una buena idea?
- 7. ¿Es una buena idea una clase de "preferencias maestras"?
- 8. ¿Es correcto (VERDADERO) una buena idea en C?
- 9. ¿Cuándo no es una buena idea pasar por referencia?
- 10. Cookies de sesión firmadas. ¿Una buena idea?
- 11. Cómo incrementar los nombres de las variables/¿Es esta una mala idea
- 12. ¿Es una buena idea usar una función CreateUUID() como sal?
- 13. Implementar una clase "LazyProperty": ¿es esta una buena idea?
- 14. ¿Es una buena idea colapsar viejas migraciones de rieles?
- 15. ¿Es buena idea la lógica comercial en los constructores?
- 16. REST Servicios web usando MVC, ¿es una buena idea?
- 17. ¿Es una buena idea cambiar dinámicamente los nombres de los subprocesos de procesamiento en Java?
- 18. activerecord como modelo, ¿es esta una buena idea?
- 19. ¿Sigue siendo una buena idea para las arquitecturas modernas?
- 20. Es una buena idea guardar gráficos en MySQL?
- 21. Django: ¿Es una buena idea generar JS dinámicamente?
- 22. ¿Es una buena práctica declarar variables "definitivas" siempre que sea posible?
- 23. ¿Es una buena idea poner db/schema.rb en .gitignore list ??
- 24. ¿Es una buena idea aprender primero LINQ, luego SQL?
- 25. ¿Puede un minificador hacer esto? (.... y ¿es una buena idea?)
- 26. cambiar a mysqli una buena idea?
- 27. ¿Cuándo se usa __call__ una buena idea?
- 28. Propagar constness a los datos apuntados por las variables miembro
- 29. ¿Son grandes los sprites CSS una buena idea?
- 30. ¿Cuál es el punto de los getters y setters?
me hizo una pregunta relacionada http://stackoverflow.com/q/3740876/15161 - tal vez las respuestas no será de ayuda. – slashmais
Pregunta incorrecta. Mejor pregunta: [¿Es una mala idea tener compradores para todos sus miembros de datos?] (Http://www.idinews.com/quasiClass.pdf) – sbi