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

autodeclaratorinitializer;

[](autoparam1, autoparam2) {};

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:

  • Solidez: si se cambia el tipo de la expresión, incluido cuando se cambia un tipo de valor devuelto de función, solo funciona.

  • Rendimiento: se garantiza 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 y nada más hará.

  • En tipos auxiliares de plantilla 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 auto palabra clave es un marcador de posición para un tipo, pero no es un tipo. Por lo tanto, la auto palabra clave no se puede usar en conversiones o operadores como sizeof y (para C++/CLI). typeid

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 encapsula una llamada a otra función y, a continuación, devuelva lo que sea el tipo de valor devuelto de esa otra función. Para obtener más información, vea decltype.

Referencias y calificadores cv

Usar auto referencias, const calificadores y volatile calificadores de caídas. 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 un int, no una int referencia, 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 auto palabra clave no se puede combinar con ningún otro especificador de tipos.
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 parámetro o argumento de plantilla no se puede declarar con la auto palabra clave .
C3535 No se puede declarar un método o un parámetro de plantilla con la auto palabra clave .
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 auto palabra clave .
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 declarado con la auto palabra clave .

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 (Tipo de variable de deduce)
sizeof operador
typeid
operator new
Declaraciones y definiciones
Ejemplos de expresiones lambda
Inicializadores
decltype