auto (C++)

Deduce el tipo de una variable declarada a partir de su expresión de inicialización.

Nota

El estándar de C++ define un significado original y revisado para esta palabra clave. Antes Visual Studio 2010, la palabra clave declara una variable en la clase de almacenamiento automático; es decir, una variable que tiene auto una duración auto local. A partir Visual Studio 2010, la palabra clave declara una variable cuyo tipo se deduce de la expresión auto de inicialización en su declaración. La /Zc:auto[-] opción del compilador controla el significado de la palabra clave auto .

Sintaxis

autoautode inicializador

[](auto[](auto, auto, auto) {};

Comentarios

La palabra clave indica al compilador que use la expresión de inicialización de una variable declarada, o parámetro de expresión auto lambda, para deducir su tipo.

Se recomienda usar la palabra clave para la mayoría de las situaciones, a menos que realmente desee una conversión, ya auto que proporciona estas ventajas:

  • Robustez: Si se cambia el tipo de la expresión (esto incluye cuando se cambia un tipo de valor devuelto de función), solo funciona.

  • Rendimiento: Se garantiza que no habrá ninguna conversión.

  • Usabilidad: No tiene que preocuparse por las dificultades ortográficas y los errores tipográficos de los nombres de tipo.

  • Eficiencia: La codificación puede ser más eficaz.

Casos de conversión en los que es posible que no quiera usar auto :

  • Cuando se desea un tipo específico y es la única alternativa.

  • Tipos auxiliares de plantillas de expresión, por ejemplo, (valarray+valarray) .

Para usar la auto palabra clave , úsela en lugar de un tipo para declarar una variable y especifique una expresión de inicialización. Además, puede modificar la palabra clave mediante especificadores y declaradores como , , pointer ( ), reference ( ) y autoconstvolatile*& rvalue reference ( && ). El compilador evalúa la expresión de inicialización y emplea esa información para deducir el tipo de la variable.

La auto expresión de inicialización puede tener varias formas:

  • 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 formularios anteriores, como auto c = { 3.14156 }; .
  • 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 se usa para declarar el parámetro de bucle en una instrucción basada en autofor intervalos, usa una sintaxis de inicialización diferente, por ejemplo for (auto& i : iterable) do_action(i); . Para obtener más información, vea Range-based Statement (C++).

La auto palabra clave es un marcador de posición para un tipo, pero no es en sí un tipo. Por lo tanto, auto la palabra clave no se puede usar en conversión u operadores como y sizeof (para C++/CLI). typeid

Utilidad

La auto palabra clave es una manera sencilla de declarar una variable que tiene un tipo complicado. Por ejemplo, puede usar para declarar una variable en la que la expresión de inicialización implica auto plantillas, punteros a funciones o punteros a miembros.

También puede usar para auto 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 más información, consulte Ejemplos de expresiones lambda.

Tipos de valor devuelto finales

Puede usar auto , junto con el decltype especificador de tipo, para ayudar a escribir bibliotecas de plantillas. Use auto y para declarar una función de plantilla cuyo tipo de valor devuelto depende de los tipos de sus decltype argumentos de plantilla. O bien, use y para declarar una función de plantilla que encapsula una llamada a otra función y, a continuación, devuelve lo que sea el tipo auto de valor devuelto de esa otra decltype función. Para obtener más información, vea decltype.

Referencias y calificadores cv

Tenga en cuenta que auto el uso de elimina const referencias, calificadores y volatile calificadores. 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 , no es una referencia, por lo que la salida es , no como sucedería si el calificador de referencia no hubiera sido intint eliminado por 11 1111 12auto .

Deducción de tipos con inicializadores entrelazados (C++14)

En el ejemplo de código siguiente se muestra cómo inicializar una auto variable mediante 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 en el uso de la palabra clave y el mensaje de error de diagnóstico correspondiente auto que emite el compilador.

Número de error Descripción
C3530 La auto palabra clave no se puede combinar con ningún otro especificador de tipo.
C3531 Un símbolo declarado con la palabra auto clave debe tener un inicializador.
C3532 Ha usado incorrectamente la auto palabra clave 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 palabra auto clave .
C3535 Un método o parámetro de plantilla no se puede declarar con la palabra auto clave .
C3536 No se puede usar un símbolo antes de inicializarlo. En la práctica, esto 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 auto clave .
C3538 Todos los símbolos de una lista de declaradores que se declaran con la auto palabra clave deben resolverse en el mismo tipo. Para obtener más información, vea Declaraciones y definiciones.
C3540, C3541 Los operadores sizeofy typeid no se pueden aplicar a un símbolo declarado con la palabra clave .

Ejemplos

Estos fragmentos de código ilustran algunas de las formas en que se puede auto usar la palabra clave .

Las declaraciones siguientes son equivalentes. En la primera instrucción, la variable j se declara como de tipo int . En la segunda instrucción, se deduce que variable es de tipo porque la expresión de inicialización kint (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 más atractivas para usar la auto palabra clave es la simplicidad.

map<int,list<string>>::iterator i = m.begin();
auto i = m.begin();

El fragmento de código siguiente declara el tipo de variables y cuándo se inician los iterelemforfor bucles de intervalo y .

// 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
    { /* ... */ }
}

El fragmento de código siguiente usa el new operador 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;

El fragmento de código siguiente inicializa la variable en el tipo , la variable en una referencia al tipo y la variable a un puntero a una x función que devuelve el tipo intyconst intfpint .

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;
    //...
}

Vea también

Palabras clave
(Deducir tipo de variable)
Operador
typeid
operator new
Declaraciones y definiciones
Ejemplos de expresiones lambda
Inicializadores
decltype