auto
(C++)
Deduce el tipo de una variable declarada a partir de su expresión de inicialización.
Nota:
El estándar C++ define un significado original y otro revisado de esta palabra clave. Antes de Visual Studio 2010, la palabra clave auto
declara una variable en la clase de almacenamiento automática; es decir, una variable que tiene una duración local. A partir de Visual Studio 2010, la palabra clave auto
declara un variable cuyo tipo se deduce de la expresión de inicialización de su declaración. La opción del compilador /Zc:auto[-]
controla el significado de la palabra clave auto
.
Sintaxis
auto
declarador inicializador;
[](auto
param1, auto
param2) {};
Comentarios
La palabra clave auto
indica al compilador que use la expresión de inicialización de una variable declarada, o el parámetro de expresión lambda, para deducir su tipo.
Se recomienda usar la palabra clave auto
en la mayoría de las situaciones, a menos que quiera realmente una conversión, porque proporciona estas ventajas:
Robustez: si se cambia el tipo de la expresión, incluyendo cuando se cambia el tipo de retorno de una función, funciona.
Rendimiento: le garantizamos que no hay ninguna conversión.
Facilidad de uso: no es necesario preocuparse por las dificultades y los errores tipográficos al escribir los nombres de los tipos.
Eficacia: la codificación puede ser más eficaz.
Casos de conversión en los que puede que no quiera usar auto
:
Quiere un tipo específico.
En los tipos de ayuda de plantillas de expresión, por ejemplo,
(valarray+valarray)
.
Use la palabra clave auto
en lugar de un tipo para declarar una variable, y especifique una expresión de inicialización. Además, puede modificar la palabra clave auto
mediante especificadores y declaradores como const
, volatile
, puntero (*
), referencia (&
) y referencia a rvalue (&&
). El compilador evalúa la expresión de inicialización y emplea esa información para deducir el tipo de la variable.
La expresión de inicialización auto
puede tener varios formatos:
- Sintaxis de inicialización universal, como
auto a { 42 };
. - Sintaxis de asignación, como
auto b = 0;
. - Sintaxis de asignación universal, que combina los dos formatos anteriores, como
auto c = { 3.14159 };
. - Inicialización directa, o sintaxis de estilo constructor, como
auto d( 1.41421f );
.
Para obtener más información, vea Inicializadores y los ejemplos de código más adelante en este documento.
Cuando auto
se usa para declarar el parámetro de bucle en una instrucción for
basada en intervalos, usa una sintaxis de inicialización diferente, por ejemplo, for (auto& i : iterable) do_action(i);
. Para obtener más información, vea Instrucción for
basada en intervalos (C++).
La palabra clave auto
es un marcador de posición para un tipo, pero no es un tipo. Por tanto, la palabra clave auto
no se puede usar en conversiones o en operadores como sizeof
y typeid
(para C++/CLI).
Utilidad
La palabra clave auto
es una manera sencilla de declarar una variable que tiene un tipo complicado. Por ejemplo, se puede usar auto
para declarar una variable en la que la expresión de inicialización implica plantillas, punteros a funciones o punteros a miembros.
También se puede usar auto
para declarar e inicializar una variable en una expresión lambda. No puede declarar el tipo de la variable porque solo el compilador conoce el tipo de una expresión lambda. Para obtener más información, vea Ejemplos de expresiones lambda.
Tipos de valor devuelto finales
Se puede usar auto
, junto con el especificador de tipo decltype
, como ayuda para escribir bibliotecas de plantillas. Use auto
y decltype
para declarar una plantilla de función cuyo tipo de valor devuelto dependa de los tipos de sus argumentos de plantilla. O bien, use auto
y decltype
para declarar una plantilla de función que encapsule una llamada a otra función y luego devuelva el tipo de valor devuelto de esa otra función. Para obtener más información, vea decltype
.
Referencias y calificadores cv
Con auto
se quitan referencias, calificadores de const
y calificadores de volatile
. Considere el ejemplo siguiente:
// cl.exe /analyze /EHsc /W4
#include <iostream>
using namespace std;
int main( )
{
int count = 10;
int& countRef = count;
auto myAuto = countRef;
countRef = 11;
cout << count << " ";
myAuto = 12;
cout << count << endl;
}
En el ejemplo anterior, myAuto es int
, no una referencia int
, por lo que la salida es 11 11
, no 11 12
, como sería el caso si el calificador de referencia no hubiera sido eliminado por auto
.
Deducción de tipos con inicializadores entre llaves (C++14)
En el ejemplo de código siguiente se muestra cómo inicializar una variable auto
con llaves. Observe la diferencia entre B y C y entre A y E.
#include <initializer_list>
int main()
{
// std::initializer_list<int>
auto A = { 1, 2 };
// std::initializer_list<int>
auto B = { 3 };
// int
auto C{ 4 };
// C3535: cannot deduce type for 'auto' from initializer list'
auto D = { 5, 6.7 };
// C3518 in a direct-list-initialization context the type for 'auto'
// can only be deduced from a single initializer expression
auto E{ 8, 9 };
return 0;
}
Restricciones y mensajes de error
En la tabla siguiente se enumeran las restricciones de uso de la palabra clave auto
y el mensaje de error de diagnóstico correspondiente que el compilador emite.
Número de error | Descripción |
---|---|
C3530 | La palabra clave auto no se puede combinar con ningún otro especificador de tipo. |
C3531 | Un símbolo que se declara con la palabra clave auto debe tener un inicializador. |
C3532 | Ha usado incorrectamente la palabra clave auto para declarar un tipo. Por ejemplo, declaró un tipo de valor devuelto de método o una matriz. |
C3533, C3539 | Un argumento de parámetro o plantilla no se puede declarar con la palabra clave auto . |
C3535 | Un parámetro de método o plantilla no se puede declarar con la palabra clave auto . |
C3536 | No se puede usar un símbolo antes de inicializarlo. En la práctica, significa que una variable no se puede usar para inicializarse a sí misma. |
C3537 | No se puede convertir a un tipo declarado con la palabra clave auto . |
C3538 | Todos los símbolos de una lista de declaradores que se declara con la palabra clave auto deben resolverse en el mismo tipo. Para obtener más información, vea Declaraciones y definiciones. |
C3540, C3541 | Los operadores sizeof y typeid no se pueden aplicar a un símbolo que se declara con la palabra clave auto . |
Ejemplos
Estos fragmentos de código muestran algunas de las formas en que se puede usar la palabra clave auto
.
Las declaraciones siguientes son equivalentes. En la primera instrucción, la variable j
se declara para que sea de tipo int
. En la segunda instrucción, se deduce que la variable k
es de tipo int
porque la expresión de inicialización (0) es un entero.
int j = 0; // Variable j is explicitly type int.
auto k = 0; // Variable k is implicitly type int because 0 is an integer.
Las declaraciones siguientes son equivalentes, pero la segunda declaración es más sencilla que la primera. Una de las razones de más peso para usar la palabra clave auto
es la sencillez.
map<int,list<string>>::iterator i = m.begin();
auto i = m.begin();
En el fragmento de código siguiente se declara el tipo de las variables iter
y elem
cuando se inician los bucles for
y range for
.
// cl /EHsc /nologo /W4
#include <deque>
using namespace std;
int main()
{
deque<double> dqDoubleData(10, 0.1);
for (auto iter = dqDoubleData.begin(); iter != dqDoubleData.end(); ++iter)
{ /* ... */ }
// prefer range-for loops with the following information in mind
// (this applies to any range-for with auto, not just deque)
for (auto elem : dqDoubleData) // COPIES elements, not much better than the previous examples
{ /* ... */ }
for (auto& elem : dqDoubleData) // observes and/or modifies elements IN-PLACE
{ /* ... */ }
for (const auto& elem : dqDoubleData) // observes elements IN-PLACE
{ /* ... */ }
}
En el fragmento de código siguiente se usa el operador new
y la declaración de puntero para declarar punteros.
double x = 12.34;
auto *y = new auto(x), **z = new auto(&x);
En el fragmento de código siguiente se declaran varios símbolos en cada instrucción de declaración. Observe que todos los símbolos de cada instrucción se resuelven en el mismo tipo.
auto x = 1, *y = &x, **z = &y; // Resolves to int.
auto a(2.01), *b (&a); // Resolves to double.
auto c = 'a', *d(&c); // Resolves to char.
auto m = 1, &n = m; // Resolves to int.
En este fragmento de código se utiliza el operador condicional (?:
) para declarar la variable x
como un entero que tiene un valor de 200:
int v1 = 100, v2 = 200;
auto x = v1 > v2 ? v1 : v2;
En el fragmento de código siguiente se inicializa la variable x
en el tipo int
, la variable y
en una referencia al tipo const int
y la variable fp
en un puntero a una función que devuelve el tipo int
.
int f(int x) { return x; }
int main()
{
auto x = f(0);
const auto& y = f(1);
int (*p)(int x);
p = f;
auto fp = p;
//...
}
Consulte también
Palabras clave
/Zc:auto
(deducir tipo de variable)
sizeof
operador
typeid
operator new
Declaraciones y definiciones
Ejemplos de expresiones lambda
Inicializadores
decltype