Palabra clave automática de C ++. ¿Por qué es mágico?

144

De todo el material que utilicé para aprender C ++, autosiempre ha sido un especificador de duración de almacenamiento extraño que no tenía ningún propósito. Pero recientemente, encontré un código que lo usaba como un nombre de tipo en sí mismo. ¡Por curiosidad lo probé, y asume el tipo de lo que sea que le asigne!

De repente, los iteradores STL y, bueno, cualquier cosa que use plantillas es 10 veces más fácil de escribir. Parece que estoy usando un lenguaje 'divertido' como Python.

¿Dónde ha estado esta palabra clave toda mi vida? ¿Arruinarás mis sueños diciendo que es exclusivo de Visual Studio o no portátil?

Anne Quinn
fuente
18
no es. magia. Es nuevo ( oh no, qué mal juego de palabras ). Ahora async es el futuro ( jadeo )
sehe
2
Aquí está la referencia sobre palabras clave automáticas en.cppreference.com/w/cpp/language/auto
andyqee

Respuestas:

149

auto era una palabra clave que C ++ "heredó" de C que había estado allí casi para siempre, pero que prácticamente nunca se usó porque solo había dos condiciones posibles: o no estaba permitida o se suponía de forma predeterminada.

El uso de autosignificar un tipo deducido era nuevo con C ++ 11.

Al mismo tiempo, auto x = initializerdeduce el tipo de xdel tipo de initializerla misma manera que la deducción de tipo de plantilla funciona para las plantillas de función. Considere una plantilla de función como esta:

template<class T>
int whatever(T t) { 
    // point A
};

En el punto A, se ha asignado un tipo en Tfunción del valor pasado para el parámetro whatever. Cuando lo hace auto x = initializer;, se utiliza la misma deducción de tipo para determinar el tipo xdel tipo initializerque se utiliza para inicializarlo.

Esto significa que la mayoría de las mecánicas de deducción de tipo que un compilador necesita implementar autoya estaban presentes y se utilizaron para plantillas en cualquier compilador que incluso intentó implementar C ++ 98/03. Como tal, agregar soporte para autoaparentemente fue bastante fácil para esencialmente todos los equipos compiladores: se agregó con bastante rapidez, y parece que también ha habido pocos errores relacionados con él.

Cuando esta respuesta se escribió originalmente (en 2011, antes de que la tinta se secara en el estándar C ++ 11) autoya era bastante portátil. Hoy en día, es completamente portátil entre todos los compiladores principales. Las únicas razones obvias para evitarlo serían si necesita escribir código que sea compatible con un compilador de C, o si tiene una necesidad específica de apuntar a algún compilador de nicho que sabe que no lo admite (por ejemplo, algunas personas aún escriben código para MS-DOS usando compiladores de Borland, Watcom, etc., que no han visto actualizaciones significativas en décadas). Si está utilizando una versión razonablemente actual de cualquiera de los compiladores principales, no hay razón para evitarla.

Jerry Coffin
fuente
23

Simplemente toma una palabra clave generalmente inútil y le da una nueva y mejor funcionalidad. Es estándar en C ++ 11, y la mayoría de los compiladores de C ++ con incluso cierta compatibilidad con C ++ 11 lo admitirán.

Nicol Bolas
fuente
Oh! Ajá, nunca pensé en C ++ el lenguaje como algo que pudiera cambiar en sí mismo. Voy a tener que buscar qué más agregaron en este C ++ 11, escuché un poco de un C ++ 0x pero nunca profundicé demasiado en él.
Anne Quinn
77
@Clairvoire C ++ 0x fue el nombre provisional. Se ha publicado este mes y, por lo tanto, se convirtió en C ++ 11.
R. Martinho Fernandes
13

Para las variables, especifica que el tipo de la variable que se declara se deducirá automáticamente de su inicializador. Para funciones, especifica que el tipo de retorno es un tipo de retorno final o se deducirá de sus declaraciones de retorno (desde C ++ 14).

Sintaxis

auto variable initializer   (1) (since C++11)

auto function -> return type    (2) (since C++11)

auto function   (3) (since C++14)

decltype(auto) variable initializer (4) (since C++14)

decltype(auto) function (5) (since C++14)

auto :: (6) (concepts TS)

cv(optional) auto ref(optional) parameter   (7) (since C++14)

Explicación

1) Al declarar variables en el alcance del bloque, en el alcance del espacio de nombres, en las declaraciones de inicialización de bucles for, etc., la palabra clave auto se puede usar como el especificador de tipo. Una vez que se ha determinado el tipo de inicializador, el compilador determina el tipo que reemplazará la palabra clave auto usando las reglas para la deducción de argumentos de plantilla a partir de una llamada de función (ver deducción de argumentos de plantilla # Otros contextos para más detalles). La palabra clave auto puede estar acompañada de modificadores, como const o &, que participarán en la deducción de tipo. Por ejemplo, dado const auto& i = expr;, el tipo de i es exactamente el tipo del argumento u en una plantilla imaginaria template<class U> void f(const U& u)si la función llamaf(expr)fue compilado Por lo tanto, auto && puede deducirse como una referencia de valor o una referencia de valor de acuerdo con el inicializador, que se utiliza en el rango para el bucle. Si se usa auto para declarar múltiples variables, los tipos deducidos deben coincidir. Por ejemplo, la declaración auto i = 0, d = 0.0;está mal formada, mientras que la declaración auto i = 0, *p = &i;está bien formada y el auto se deduce como int.

2) En una declaración de función que utiliza la sintaxis de tipo de retorno final, la palabra clave auto no realiza la detección automática de tipo. Solo sirve como parte de la sintaxis.

3) En una declaración de función que no utiliza la sintaxis de tipo de retorno final, la palabra clave auto indica que el tipo de retorno se deducirá del operando de su declaración de retorno utilizando las reglas para la deducción de argumentos de plantilla.

4) Si el tipo declarado de la variable es decltype (auto), la palabra clave auto se reemplaza con la expresión (o lista de expresiones) de su inicializador, y el tipo real se deduce usando las reglas para decltype.

5) Si el tipo de retorno de la función se declara decltype (auto), la palabra clave auto se reemplaza con el operando de su declaración return, y el tipo de retorno real se deduce usando las reglas para decltype.

6) Un especificador de nombre anidado de la forma auto :: es un marcador de posición que se reemplaza por una clase o tipo de enumeración que sigue las reglas para la deducción de marcador de posición de tipo restringido.

7) Una declaración de parámetro en una expresión lambda. (desde C ++ 14) Una declaración de parámetro de función. (conceptos TS)

Notas Hasta C ++ 11, auto tenía la semántica de un especificador de duración de almacenamiento. Mezclar variables automáticas y funciones en una declaración, como en auto f() -> int, i = 0;no está permitido.

Para más información: http://en.cppreference.com/w/cpp/language/auto

Prathamesh Aware
fuente
11

Esta funcionalidad no ha estado allí toda su vida. Ha sido compatible con Visual Studio desde la versión 2010. Es una nueva característica de C ++ 11, por lo que no es exclusiva de Visual Studio y es / será portátil. La mayoría de los compiladores ya lo admiten.

R. Martinho Fernandes
fuente
3

No va a ninguna parte ... es una nueva característica estándar de C ++ en la implementación de C ++ 11. Dicho esto, si bien es una herramienta maravillosa para simplificar las declaraciones de objetos, así como para limpiar la sintaxis de ciertos paradigmas de llamadas (es decir, bucles for basados ​​en rangos), no lo use en exceso ni lo abuse :-)

Jason
fuente
3

La palabra clave auto especifica que el tipo de la variable que se declara se deducirá automáticamente de su inicializador. En el caso de las funciones, si su tipo de retorno es automático, entonces se evaluará mediante la expresión de tipo de retorno en tiempo de ejecución.

Puede ser muy útil cuando tenemos que usar el iterador. Por ejemplo, para el siguiente código, simplemente podemos usar el "auto" en lugar de escribir la sintaxis completa del iterador.

int main() 
{ 

// Initialize set 
set<int> s; 

s.insert(1); 
s.insert(4); 
s.insert(2); 
s.insert(5); 
s.insert(3); 

// iterator pointing to 
// position where 2 is 
auto pos = s.find(3); 

// prints the set elements 
cout << "The set elements after 3 are: "; 
for (auto it = pos; it != s.end(); it++) 
    cout << *it << " "; 

return 0; 
}

Así es como podemos usar la palabra clave "auto"

rahul goyal
fuente
0

Es mágico es su capacidad de reducir la necesidad de escribir código para cada tipo de variable que se pasa a funciones específicas. Considere una función similar a Python print () en su base C.

#include <iostream>
#include <string>
#include <array>

using namespace std;

void print(auto arg) {
     cout<<arg<<" ";
}

int main()
{
  string f = "String";//tok assigned
  int x = 998;
  double a = 4.785;
  string b = "C++ Auto !";
//In an opt-code ASCII token stream would be iterated from tok's as:
  print(a);
  print(b);
  print(x);
  print(f);
}
rodeone2
fuente