C ++: referencia constante, antes vs después del especificador de tipo

145

¿Cuál es la diferencia entre los argumentos en:

int foo1(const Fred &arg) {
...
}

y

int foo2(Fred const &arg) {
...
}

? No veo este caso cubierto en las preguntas frecuentes de parashift.

eisbaw
fuente
2
¿Es esta una pregunta sobre el estilo? "const Fred" suena bien en inglés, pero "Fred const" me parece mejor.
LatinSuD
1
En una nota relacionada, ¿hay alguna razón se debe preferir Fred const &argmás Fred const& arg? Este último me gusta más porque const&es una unidad que significa "constref", y el nombre argestá separado por un espacio en blanco de todos los especificadores de tipo.
Frank
44
@dehmann: Pero int const& refno significa 'const ref' sino 'ref to const'.
Cedric H.
1
Duplicado de: stackoverflow.com/questions/2640446/…
Michael Aaron Safyan

Respuestas:

112

No hay diferencia ya que const se lee de derecha a izquierda con respecto a &, por lo que ambos representan una referencia a una instancia de Fred inmutable.

Fred& constsignificaría que la referencia en sí es inmutable, que es redundante ; cuando se trata de punteros const tanto Fred const*y Fred* constson válidas pero diferentes.

Es una cuestión de estilo, pero prefiero usarlo constcomo sufijo ya que se puede aplicar de manera consistente, incluidas las funciones de miembro constante .

Sean Fausett
fuente
Entonces, ¿qué es un punto para hacer std::is_const<const T&>::valueser false?
abys.7
@ abyss.7 que es una referencia a const T; La referencia es mutable.
Sean Fausett
125

Comportamiento

No hay diferencia semántica entre const T&y T const&; el lenguaje los trata como el mismo tipo. (Lo mismo se aplica a const T*y T const*.)

Como una cuestión de estilo

Sin embargo, con respecto a cuál debe preferir estilísticamente, discreparé de muchas de las otras respuestas y preferiré const T&(y const T*):

  • const T&es el estilo utilizado en el libro del lenguaje de programación C ++ de Stroustrup .
  • const T& es el estilo utilizado en el estándar C ++ en sí.
  • const T*es el estilo utilizado en el lenguaje de programación C de K&R .
  • const T* es el estilo usado en el estándar C.
  • Debido a los factores anteriores, creo const T&/ const T*tengo mucha más inercia que T const&/ T const*. const T&/ const T*empíricamente me parece mucho más común que T const&/T const* en todos los códigos C ++ y C que he visto. Creo que seguir las prácticas comunes es más legible que adherirse dogmáticamente a las reglas de análisis de derecha a izquierda.
  • Con T const*, parece más fácil extraviar el *como T* const(especialmente si las personas no están tan acostumbradas). En contraste, const* Tno es sintaxis legal.

¿Qué pasa con la regla de análisis de derecha a izquierda?

Con respecto al argumento de análisis de derecha a izquierda que a la gente parece encantarle usar: como mencioné en un comentario a otra respuesta, también se const T&lee bien de derecha a izquierda. Es una referencia a una constante de T. "T" y "constante" cada uno puede funcionar como un adjetivo o un sustantivo. (Además, leer de T const*derecha a izquierda puede ser ambiguo, ya que podría interpretarse incorrectamente como "puntero constante a T" en lugar de "puntero a constante T").

jamesdlin
fuente
3
+1, de acuerdo. Al leer el código, es más fácil detectar una constante si la línea comienza con constante. La regla derecha-izquierda solo es necesaria cuando se analiza manualmente las declaraciones de tipo especialmente peludas. ¿Por qué no optimizar para el caso más común? Además, en mi humilde opinión, si escribe declaraciones de tipo, por lo que necesita ejecutar manualmente un FSM en su cabeza, lo está haciendo mal.
Andreas Magnusson el
2
-1. Independientemente de cuán justificadas estén sus conclusiones y cuánto estoy personalmente de acuerdo con ellas, no están respondiendo la pregunta directamente. Esto hace que la segunda respuesta a una pregunta simple parezca un galimatías fuera de tema sobre una maquinaria submarina desordenada, sin conclusiones, sin respuesta directa, nada. Obtendrá mi voto positivo cuando agregue un resumen simple y claro que indique " No, no hay diferencia semántica entre ambas sintaxis , pero hay algunas consideraciones estilísticas de la siguiente manera ...". Y solo entonces todas esas balas.
ulidtko
1
OMI, la razón se const T&lee mejor, es que: 1- Leemos el código de izquierda a derecha. Y 2- Al describir un nuevo concepto partimos del concepto más general al más específico. Aquí, la constpalabra clave es más general ya que secciona el espacio variable en dos categorías, mientras que el especificador de tipo lo divide en muchas.
pooya13
"puntero a" debe permanecer juntos. Así que no hay ambigüedad paraT const*
Dexter
13

Aunque son uno y lo mismo, para mantener la coherencia con la regla DERECHA-IZQUIERDA sobre el análisis de las declaraciones C y C ++, es mejor escribirFred const &arg

Consulte también esto para desarrollar una mayor comprensión sobre las declaraciones, calificadores y declaradores.

Chubsdad
fuente
1
Prefiero el sufijo, porque funciona mejor con la typedefexpansión. Ejemplo: typedef int* pointer;, const pointer no es const int* , es int* const. La forma del sufijo no es incómoda.
Matthieu M.
44
La OMI también const T&lee bien de derecha a izquierda; Es una referencia a una constante T. Ty constantcada uno puede funcionar como un adjetivo o un sustantivo.
jamesdlin
7

Ambos funcionan, y aquí está la explicación del hombre que lo escribió.
Para citarlo:

¿Por qué? Cuando inventé "const" (inicialmente llamado "solo lectura" y tenía un "solo escritura" correspondiente), permití que fuera antes o después del tipo porque podía hacerlo sin ambigüedad.

Defecto
fuente
3

Las referencias no funcionan de la misma manera que los punteros: para los punteros puede tener 'punteros constantes' ( type * const p) y 'puntero a constante' ( const type * po type const * p).

Pero no tiene esto para referencias: una referencia siempre se referirá al mismo objeto; en ese sentido, puede considerar que las 'referencias' son 'referencias constantes' (de la misma manera que puede tener 'punteros constantes').

Por lo tanto, algo como 'type & const ref' no es legal. Solo puede tener 'referencia al tipo' ( type &ref) y 'referencia al tipo constante' ( const type &refo type const &ref; ambos son exactamente equivalentes).

Una última cosa: incluso si const typesuena más correcto en inglés, la escritura type constpermite una comprensión más sistemática de las declaraciones "de derecha a izquierda": int const & refse puede leer has 'ref es una referencia a un int constante'. O un ejemplo más complicado:, int const * const & refref es una referencia a un puntero constante a un int constante.

Conclusión: en su pregunta, ambos son exactamente equivalentes.

Cedric H.
fuente