auto — słowo kluczowe (typ odliczenia)
Wnioskowanie typu zadeklarowanej zmiennej na podstawie jej wyrażenia inicjującego.
auto declarator initializer;
Uwagi
Słowo kluczowe auto wskazuje kompilatorowi użycie wyrażenia inicjującego zadeklarowanej zmiennej do wywnioskowania jej typu.
Firma Microsoft zaleca użycie słowa kluczowego auto w większości sytuacji - chyba, że użytkownik naprawdę chce konwersji - ponieważ zapewnia to następujące korzyści:
Niezawodność: Jeśli zmienił się typ wyrażenia - obejmuje to zmianę zwracanego typu funkcji - po prostu działa.
Wydajność: Gwarancja braku konwersji.
Użyteczność: Nie trzeba martwić się o trudności pisowni nazwy typu i literówki.
Wydajność: Programowanie może być bardziej efektywne.
Przypadki konwersji, w których użytkownik może nie chcieć używać auto:
Kiedy koniecznie potrzebny jest określony typ.
Typy pomocnika szablonu wyrażenia - na przykład (valarray+valarray) i inicjator list - choć użytkownik raczej nie będzie pisał auto x = { 1 }; i spodziewał się otrzymać int.
Aby skorzystać ze słowa kluczowego auto, należy użyć go zamiast typu przy deklaracji zmiennej, a następnie określić wyrażenie inicjujące.Ponadto, można modyfikować słowo kluczowe auto przy użyciu specyfikatorów i deklaratorów takich jak const, volatile, wskaźnik (*), odwołanie (&) i odwołanie do r-wartości (&&).Kompilator oblicza wyrażenie inicjujące, a następnie używa tej informacji do wywnioskowania typu zmiennej.
Wyrażenie inicjujące może być przypisaniem (składnia znaku równości), bezpośrednią inicjacją (składnia funkcyjna), wyrażeniem z operatorem new lub może być parametrem for-range-declaration w instrukcji Range-based for — instrukcja (C++) .Aby uzyskać więcej informacji, zobacz Inicjatory i przykłady kodu w dalszej części tego dokumentu.
Słowo kluczowe auto jest symbolem zastępczym dla typu, ale samo nie jest typem.W związku z tym słowo kluczowe auto nie może zostać użyte w rzutowaniu lub operatorach takich jak sizeof i TypeID.
Użyteczność
Słowo kluczowe auto pozwala w prosty sposób zadeklarować zmienną, która ma typ złożony.Na przykład, można użyć auto, aby zadeklarować zmienną, jeżeli wyrażenie inicjujące obejmuje szablony, wskaźniki do funkcji lub wskaźniki do elementów członkowskich.
Można również użyć auto, aby zadeklarować i zainicjować zmienną do wyrażenia lambda.Nie można samodzielnie zadeklarować typu zmiennej, ponieważ typ wyrażenia lambda jest znany tylko kompilatorowi.Aby uzyskać więcej informacji, zobacz Przykłady wyrażeń lambda.
Śledzenie zwracanych typów
Można użyć auto, wraz ze specyfikatorem typu decltype, aby pomóc w pisaniu bibliotek szablonu.Należy używać auto i decltype do deklarowania funkcji szablonu, którego zwracany typ zależy od typów argumentów szablonu.Zamiast tego można użyć auto i decltype, aby zadeklarować funkcję szablonu, która otacza wywołanie do innej funkcji, a następnie zwraca typ taki, jaki zwraca ta inna funkcja.Aby uzyskać więcej informacji, zobacz decltype — specyfikator typu.
Odwołania i kwalifikatory cv
Należy zauważyć, że używanie auto porzuca odwołania, a także kwalifikatory const i volatile.Rozważmy następujący przykład:
// 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;
}
Może się wydawać, że myAuto jest odwołaniem do wartości typu int, ale nie jest.Jest po prostu wartością typu int, więc wyjście to 11 11, a nie 11 12 jak byłoby w przypadku, gdy odwołanie nie zostałoby usunięte przez auto.
Ograniczenia i komunikaty o błędach
Poniższa lista zawiera ograniczenia dotyczące stosowania słowa kluczowego auto, a także odpowiadający im komunikat błędu diagnostycznego emitowanego przez kompilator.
Numer błędu |
Opis |
---|---|
Słowo kluczowe auto nie może zostać połączone z żadnym innym specyfikatorem typu. |
|
Symbol, który jest zadeklarowany za pomocą słowa kluczowego auto musi mieć inicjatora. |
|
Nieprawidłowo użyto słowa kluczowego auto, aby zadeklarować typ.Na przykład zadeklarowano typ zwracany przez metodę lub tablicę. |
|
Nie można zadeklarować argumentu parametru lub szablonu z wykorzystaniem słowa kluczowego auto. |
|
Symbol, który jest zadeklarowany za pomocą słowa kluczowego auto w wyrażeniu new musi mieć inicjatora.Aby uzyskać więcej informacji, zobacz operator new (<new>). |
|
Nie można zadeklarować parametru szablonu lub metody z wykorzystaniem słowa kluczowego auto. |
|
Nie można użyć symbolu, zanim zostanie zainicjowany.W praktyce oznacza to, że zmienna nie może zostać użyta do zainicjowania samej siebie. |
|
Nie można rzutować na typ, który jest zadeklarowany za pomocą słowa kluczowego auto. |
|
Wszystkie symbole na liście deklaratora, która jest zadeklarowana za pomocą słowa kluczowego auto, muszą być rozpoznane jako ten sam typ.Aby uzyskać więcej informacji, zobacz Deklaracje. |
|
Operatory sizeof i TypeID nie mogą być zastosowane do symbolu, który jest zadeklarowany za pomocą słowa kluczowego auto. |
Przykłady
Poniższe fragmenty kodu ilustrują niektóre ze sposobów, w jakie można użyć słowa kluczowego auto.
Następujące deklaracje są równoważne.W pierwszej instrukcji, zmienna j została zadeklarowana jako typ int.W drugiej instrukcji, wywnioskowano, że zmienna k powinna być typu int, ponieważ wyrażenie inicjujące (0) jest liczbą całkowitą.
int j = 0; // Variable j is explicitly type int.
auto k = 0; // Variable k is implicitly type int because 0 is an integer.
Następujące deklaracje są równoważne, ale druga deklaracja jest prostsza niż pierwsza.Jednym z najbardziej istotnych powodów do korzystania ze słowa kluczowego auto jest prostota.
map<int,list<string>>::iterator i = m.begin();
auto i = m.begin();
Poniższy fragment kodu deklaruje typ zmiennych iter i elem, gdy rozpoczynają się pętle for i zakres 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
{ /* ... */ }
}
Następujący fragment kodu używa operatora new i deklaracji wskaźnika, aby zadeklarować wskaźniki.
double x = 12.34;
auto *y = new auto(x), **z = new auto(&x);
Następny fragment kodu deklaruje wiele symboli w każdej instrukcji deklaracji.Należy zauważyć, że wszystkie symbole w każdej instrukcji są rozpoznawane jako ten sam typ.
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.
Poniższy fragment kodu używa operatora warunkowego (?:), aby zadeklarować zmienną x jako integer, który ma wartość 200:
int v1 = 100, v2 = 200;
auto x = v1 > v2 ? v1 : v2;
Poniższy fragment kodu inicjuje zmienną x typu int, zmienną y jako odwołanie do typu constint, a także zmienną fp jako wskaźnik do funkcji, która zwraca typ 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;
//...
}
Zobacz też
Informacje
Specyfikatory klas magazynowania