Estoy emocionado de usar las variables auto en mis programas C ++. Sé que las variables declaradas con auto usan reglas de plantilla para deducir los tipos de variables, pero estoy confundido sobre cómo funciona eso para los tipos numéricos. Supongamos que tengo:

auto foo = 12;

El tipo de foo podría ser razonablemente int o incluso unsigned char. Pero supongamos que más adelante en mi programa hago algunos cálculos y le asigno un valor de 4 mil millones. En ese punto, me gustaría que foo se convierta en tipo unsigned int o tal vez long.

¿Cómo pueden los compiladores anticipar los valores que se asignarán más adelante en el programa?

22
David Lobron 26 feb. 2018 a las 18:01

6 respuestas

La mejor respuesta

El compilador trabaja con la información presente, que en su caso es el literal entero 12. Por lo tanto, deduce que foo es del tipo int. No anticipa nada. Puede usar el sufijo literal entero adecuado:

auto foo = 12ul;

Para forzar que foo se deduzca como unsigned long. No puede definir que la variable sea del tipo int y luego en la línea espere que el compilador la cambie de algún modo a otro tipo solo porque asignó un valor diferente que no encajará en el tipo utilizado anteriormente. Si lo hiciera, simplemente se produciría un desbordamiento de enteros, que es un comportamiento indefinido.

Para obtener más información sobre el tema, consulte el especificador automático y referencia de deducción automática de tipo.

50
Ron 26 feb. 2018 a las 15:45

Personalmente, no usaría auto para estas constantes inmediatas, pero donde el valor proviene de otra llamada a método, o asignado desde otra variable.

Si desea una forma de definir una variable para que coincida con el tipo de otra variable, de modo que pueda interactuar con ella, pero desea asignar un valor constante, entonces use decltype para asegurarse de que su tamaño sea compatible:

decltype(otherVar) myVar = 1234;
myVar += otherVar;  // will work just as well as otherVar += myVar

En cualquier caso, el tipo se especifica mediante la constante literal, y un 12 sin decorar definirá un int.

Sin embargo, puede decorar su constante con U, para que no esté firmada, o L para que sea larga, o incluso LL para que sea muy larga. ¡No hay equivalente para forzarlo en corto o char, desafortunadamente!

1
Gem Taylor 1 mar. 2018 a las 14:36

"El tipo de foo podría ser razonablemente int o incluso sin firmar char"

No, no puede. Cada expresión en C ++ tiene un tipo, y eso está claramente definido en el lenguaje. En su caso, la expresión es un literal entero, por lo que el tipo corresponde al literal. El tipo específico es definido por las reglas:

El tipo del literal

El tipo de literal entero es el primer tipo en el que puede caber el valor, de la lista de tipos que depende de qué base numérica y qué sufijo de entero se utilizó.

sin sufijo - int, long int, long long int (desde C ++ 11)

"¿Cómo pueden los compiladores anticipar valores que se asignarán más adelante en el programa? "

No puede. El tipo se determina cuando declara la variable y no se puede cambiar más tarde.

23
StoryTeller - Unslander Monica 26 feb. 2018 a las 15:37

El tipo para foo podría ser razonablemente int o incluso unsigned char

podría ser muchas cosas, pero en realidad es solo una cosa.

El literal entero 12 tiene el tipo int.

Período.

Pero supongamos que más adelante en mi programa, hago algunos cálculos y le asigno un valor de 4 mil millones. En ese punto, me gustaría que foo tuviera un tipo unsigned int o tal vez largo. ¿Cómo pueden los compiladores anticipar los valores que se asignarán más adelante en el programa?

No pueden y no lo hacen. El tipo de foo no cambiará. foo no tiene el tipo auto (no existe tal cosa); tiene el tipo int. Su programa en adelante será como si hubiera escrito int foo = 12;. La deducción / automatización termina allí.

10
Lightness Races in Orbit 26 feb. 2018 a las 15:23

En ese punto, me gustaría que foo tenga el tipo unsigned int o tal vez long.

Esa no es la forma en que funciona el lenguaje. Una variable no puede cambiar su tipo en tiempo de ejecución. Si define e inicializa una variable como auto foo = 12;, eso significa exactamente lo mismo que int foo = 12;, independientemente de cualquier asignación futura, porque el tipo de 12 es int.

¿Cómo pueden los compiladores anticipar los valores que se asignarán más adelante en el programa?

No tienen que hacerlo. Los valores que se asignan más tarde se convertirán al tipo de la variable. Si el valor está fuera de rango para ese tipo, las reglas exactas dependen de los tipos con los que está tratando.

5
27 feb. 2018 a las 17:23

Mi consejo es que este no es un buen lugar para usar auto. Usted sabe qué factores determinan el tipo que necesita, y no se pueden deducir del contexto inmediato. (Sin embargo, si puede escribir sus variables como asignaciones estáticas únicas, eso nunca sucederá).

Si sabe que la variable necesita poder mantener un valor de al menos 4 mil millones, declare como unsigned long o long long int. O, si realmente desea codificar a la defensiva contra elecciones desafortunadas para el ancho de esos tipos (como plataformas donde long tiene 32 bits de ancho para admitir código heredado, pero el tamaño de la palabra nativa es de 64 bits), declare como uint_fast32_t o int_fast64_t. O si quieres el más pequeño, no el más rápido, uint_least32_t. (¡A veces, el código más rápido es el que mantiene la mayoría de los valores en el caché!)

Si lo que realmente quiere es el tipo con o sin signo más rápido que puede contener un valor de 4 mil millones, ¡diga lo que quiere decir!

4
Davislor 26 feb. 2018 a las 17:36