tutorialspoint significado pointer pass c++ syntax pointers reference types

c++ - pass - pointers significado



¿Por qué algunas personas prefieren "T const &" a "const T &"? (8)

Creo que algunas personas simplemente prefieren leer las declaraciones de derecha a izquierda. const aplica al token de la izquierda, excepto cuando no hay nada allí y se aplica en el token de la derecha. Por lo tanto, const T& implica la cláusula "except" y tal vez se lo pueda considerar más complicado (en realidad ambos deberían ser tan fáciles de entender).

Comparar:

const T* p; (pointer to T that is const) T const* p; (pointer to const T) //<- arguable more natural to read T* const p; (const pointer to T)

Entonces, me doy cuenta de que const T& T const& son idénticos y ambos significan una referencia a un const T. En ambos casos, la referencia también es constante (las referencias no pueden reasignarse, a diferencia de los punteros). He observado, en mi experiencia algo limitada, que la mayoría de los programadores de C ++ usan const T& , pero he encontrado algunas personas que usan T const& . Uso const T& simplemente porque lo aprendí de esa manera, y por eso T const& parece un poco gracioso. ¿Cuál es la razón por la que usa la variante que usa? ¿Alguno de ustedes trabaja en una organización para la cual los estándares de codificación exigen el uso de una variante sobre la otra?

Editar
Según las respuestas, parece que una de las razones para elegir entre los dos es si desea leerlo como el compilador (de derecha a izquierda) o como en inglés (de izquierda a derecha). Si uno lo lee como el compilador, entonces "T const &" se lee como "& (referencia) const (a una constante) T (de tipo T)". Si uno lo lee como inglés, de izquierda a derecha, entonces "const T &" se lee como "un objeto constante de tipo T en forma de una referencia". Prefiero leerlo como la prosa inglesa, pero ciertamente puedo ver el sentido de interpretarlo como lo hace el compilador.

Nadie ha respondido a la pregunta sobre la organización o las normas de codificación, pero sospecho firmemente que la mayoría de las organizaciones no imponen un mandato sobre el otro, aunque podrían esforzarse por lograr coherencia.


Creo que es preferencia personal. No hay diferencia entre las dos variantes.


Dado que el código está basado predominantemente en inglés, los programadores tienden a leer de izquierda a derecha, por lo tanto, nos const T& forma natural cuando el compilador lo lee de derecha a izquierda, de modo que T const& lee de forma natural (referencia a const T)


Eso es porque a algunos les resulta útil leer la declaración de derecha a izquierda.

char const* const char*

Ambos son punteros a const char.


Esto marcará la diferencia cuando tengas más de un modificador const / volátil. Luego, ponerlo a la izquierda del tipo sigue siendo válido, pero romperá la consistencia de toda la declaración. Por ejemplo:

T const * const *p;

significa que p es un puntero para const pointer para const T y lees consecuentemente de derecha a izquierda.

const T * const *p;

significa lo mismo, pero se pierde la consistencia y debe recordar que la const / volátil más a la izquierda está ligada a T solo y no a T *.


Mi razonamiento es el siguiente:

Parece que sale mejor de la lengua si escribe "const T &", pero cuando lo hace, termina con la "referencia T constante" ambigua. He visto esto causar problemas más de una vez en la comprensibilidad del código que permitió a alguien, incluso semi-experimentado, malinterpretar lo que significaba algo o cómo declarar un tipo más complejo.

No puedo pensar en ningún ejemplo en este momento, pero más de una vez respondí preguntas sobre declaraciones de tipo y constness donde el problema fue causado por el hábito de usar "const T &" en lugar de "T const &". También solía escribirlo de esa manera y cuando me convertí en un desarrollador sénior, alguien a cargo de la tutoría y la creación de estándares de código en proyectos, me resultó mucho más fácil para los desarrolladores de nivel de entrada cuando obligo a todos a utilizar "T const &". Supongo que un error bastante trivial y de novato sería ¿por qué compila este código?

const T* t = f(); t = 0; // assignment to const?? - no, it is not the T* that is const, just the T.

Cuando aprende a leerlo de la forma en que lo hace el compilador, es mucho más fácil entender qué tipo de complejo es y además le permite declarar más fácilmente tipos complejos cuando lo necesite. Por tipos complejos estoy hablando de cosas como:

T const * const &

Cuando sabes que el compilador lee de derecha a izquierda, de adentro hacia afuera, lo que eso significa se vuelve bastante aparente y cuando es necesario escribir uno puedes hacerlo fácilmente: referencia al puntero constante a una constante T. Ahora escribe la declaración de un "referencia a un puntero a un puntero constante a una T". Si simplemente usa la notación de izquierda a derecha, creo que encontrará esto bastante fácil.

En resumen, aunque inicialmente parece poco natural enseñar a usar la gramática de derecha a izquierda TODO el tiempo, en lugar de solo cuando es necesario (porque a menudo lo es), le resultará mucho más fácil recordar lo que significa una línea de código y cómo escribir lo que quieres decir. Es algo así como lo que rechazo "," en declaraciones:

T* ptr1 = 0, ptr2 = 0; // oops!!!

// do it this way please! T* ptr1 = 0; T* ptr2 = 0;

Técnicamente, es lo mismo, pero cuando tratas de hacer que un grupo de personas de distintas capacidades trabajen sobre la misma cosa, tenderás a asegurarte de que todos usen el método que sea más fácil de entender y usar. Mi experiencia me ha enseñado que "T const &" es ese método.


Si encuentras esta discusión interesante, probablemente encuentres interesante this artículo de Dan Saks. No aborda directamente su pregunta, pero explica por qué prefiere

VP const foo[];

a

const VP foo[];

Es porque dado

typedef void *VP;

fácilmente podría ser engañado al pensar que el segundo ejemplo anterior significa

const void *foo[]; // Wrong, actually: void *const foo[];

pero el primer ejemplo es más difícil de malinterpretar.


Solía ​​ser un gran defensor de const T& porque lee lógicamente de izquierda a derecha (es una referencia T constante ). (Y probablemente haya algún sesgo ya que la mayoría del código que encontré en ese punto se escribió de esa manera).

A lo largo de los años, me he encontrado con algunos casos de esquina (como múltiples punteros / capas de referencia, declaraciones de variables múltiples y punteros de método) que tensan un poco las cosas por las razones que otras personas ya han respondido. A menudo, la introducción de tipos adicionales te ayuda a "despegar" estos casos hasta cierto punto, pero luego tienes que encontrar un nombre para algo incluso si solo se usa una vez.

El punto de inflexión para mí fue la introducción del auto en C ++ 11, especialmente cuando se combina con el rango-basado-para. Con eso, he invertido y ahora prefiero mucho T const& (o "referencia a T constante", leyendo de derecha a izquierda). No solo es más consistente con la forma en que el compilador realmente analiza, sino que cuando reemplazas el tipo con auto , esto siempre termina a la izquierda, que creo que se lee mejor.

Comparar:

for (const T& a : list) for (T& a : list) for (T const& a : list) for (T& a : list) for (const auto& a : list) for (auto& a : list) for (auto const& a : list) for (auto& a : list)

Tenga en cuenta también la columna de la derecha, donde he agregado la versión no const de la misma. Al menos para mí, la const frente a la no const y la automática frente a la explícita parecen ser más consistentes en los casos en que const aparece después de T.

Pero esta es una elección de estilo, y como tal, no hay una respuesta absolutamente correcta.