C ++ Auto-Schlüsselwort. Warum ist es Magie?

144

Von all dem Material, das ich zum Erlernen von C ++ verwendet habe, autowar es immer ein seltsamer Spezifizierer für die Speicherdauer, der keinen Zweck erfüllt hat. Aber erst kürzlich bin ich auf Code gestoßen, der ihn als Typnamen an und für sich verwendet hat. Aus Neugier habe ich es versucht und es nimmt die Art von allem an, was ich ihm zuordne!

Plötzlich sind STL-Iteratoren und alles, was Vorlagen verwendet, zehnmal einfacher zu schreiben. Es fühlt sich an, als würde ich eine "lustige" Sprache wie Python verwenden.

Wo war dieses Schlüsselwort mein ganzes Leben lang? Wirst du meine Träume zerstören, indem du sagst, dass es exklusiv für Visual Studio oder nicht tragbar ist?

Anne Quinn
quelle
18
es ist nicht. Magie. Es ist neu ( oh nein, was für ein schlechtes Wortspiel ). Jetzt ist
Async
2
Hier ist die Referenz über Auto-Keywords en.cppreference.com/w/cpp/language/auto
andyqee

Antworten:

149

auto war ein Schlüsselwort, das C ++ von C "geerbt" hat, das fast für immer da war, aber praktisch nie verwendet wurde, weil es nur zwei mögliche Bedingungen gab: Entweder war es nicht erlaubt oder es wurde standardmäßig angenommen.

Die Verwendung autoeines abgeleiteten Typs war in C ++ 11 neu.

Zur gleichen Zeit, auto x = initializerfolgert der den Typen xvon der Art der initializergleichen Art und Weise wie Template - Typ Abzug Arbeiten für Funktionsschablonen. Stellen Sie sich eine Funktionsvorlage wie diese vor:

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

An Punkt A wurde Tbasierend auf dem für den Parameter an übergebenen Wert ein Typ zugewiesen whatever. Wenn Sie dies tun auto x = initializer;, wird der gleiche Typabzug verwendet, um den Typ für xden Typ zu bestimmen initializer, der zum Initialisieren verwendet wird.

Dies bedeutet, dass die meisten Typabzugsmechanismen, die ein Compiler implementieren muss, autobereits vorhanden waren und für Vorlagen auf jedem Compiler verwendet wurden, der sogar versucht hat, C ++ 98/03 zu implementieren. Daher war das Hinzufügen von Unterstützung für autoim Wesentlichen alle Compilerteams anscheinend recht einfach - es wurde ziemlich schnell hinzugefügt, und es scheint auch nur wenige Fehler zu geben, die damit zusammenhängen.

Als diese Antwort ursprünglich geschrieben wurde (2011, bevor die Tinte auf dem C ++ 11-Standard trocken war), autowar sie bereits ziemlich portabel. Heutzutage ist es unter allen gängigen Compilern durchaus portabel. Die einzigen offensichtlichen Gründe, dies zu vermeiden, sind, wenn Sie Code schreiben müssen, der mit einem C-Compiler kompatibel ist, oder wenn Sie speziell auf einen Nischen-Compiler abzielen müssen, von dem Sie wissen, dass er ihn nicht unterstützt (z. B. schreiben einige Leute immer noch Code für MS-DOS mit Compilern von Borland, Watcom usw., die seit Jahrzehnten keine wesentlichen Verbesserungen erfahren haben). Wenn Sie eine einigermaßen aktuelle Version eines der Mainstream-Compiler verwenden, gibt es keinen Grund, dies überhaupt zu vermeiden.

Jerry Sarg
quelle
23

Es geht nur darum, ein allgemein nutzloses Schlüsselwort zu verwenden und ihm eine neue, bessere Funktionalität zu geben. Es ist Standard in C ++ 11, und die meisten C ++ - Compiler mit sogar etwas C ++ 11-Unterstützung werden es unterstützen.

Nicol Bolas
quelle
Oh! Aha, ich hätte nie gedacht, dass C ++ die Sprache eine Sache ist, die sich an und für sich ändern könnte. Ich muss nachsehen, was sie sonst noch in diesem C ++ 11 hinzugefügt haben. Ich habe ein wenig von einem C ++ 0x gehört, aber nie zu tief hineingegraben.
Anne Quinn
7
@Clairvoire C ++ 0x war der vorläufige Name. Es wurde diesen Monat veröffentlicht und wurde somit zu C ++ 11.
R. Martinho Fernandes
13

Gibt für Variablen an, dass der Typ der deklarierten Variablen automatisch von ihrem Initialisierer abgeleitet wird. Gibt für Funktionen an, dass der Rückgabetyp ein nachfolgender Rückgabetyp ist oder aus seinen Rückgabeanweisungen abgeleitet wird (seit C ++ 14).

Syntax

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)

Erläuterung

1) Beim Deklarieren von Variablen im Blockbereich, im Namespace-Bereich, in Initialisierungsanweisungen von for-Schleifen usw. kann das Schlüsselwort auto als Typbezeichner verwendet werden. Sobald der Typ des Initialisierers bestimmt wurde, bestimmt der Compiler den Typ, der das Schlüsselwort auto ersetzt, anhand der Regeln für den Abzug von Vorlagenargumenten aus einem Funktionsaufruf (Einzelheiten finden Sie unter Abzug von Vorlagenargumenten # Andere Kontexte). Das Schlüsselwort auto kann von Modifikatoren wie const oder & begleitet werden, die am Typabzug teilnehmen. Zum Beispiel ist const auto& i = expr;der Typ von i genau der Typ des Arguments u in einer imaginären Vorlage, template<class U> void f(const U& u)wenn der Funktionsaufruff(expr)wurde zusammengestellt. Daher kann auto && entweder als l-Wert-Referenz oder als r-Wert-Referenz gemäß dem Initialisierer abgeleitet werden, der in einer bereichsbasierten for-Schleife verwendet wird. Wenn auto zum Deklarieren mehrerer Variablen verwendet wird, müssen die abgeleiteten Typen übereinstimmen. Zum Beispiel ist die Deklaration auto i = 0, d = 0.0;schlecht geformt, während die Deklaration auto i = 0, *p = &i;wohlgeformt ist und das Auto als int abgeleitet wird.

2) In einer Funktionsdeklaration, die die Syntax des nachfolgenden Rückgabetyps verwendet, führt das Schlüsselwort auto keine automatische Typerkennung durch. Es dient nur als Teil der Syntax.

3) In einer Funktionsdeklaration, die nicht die Syntax des nachfolgenden Rückgabetyps verwendet, gibt das Schlüsselwort auto an, dass der Rückgabetyp unter Verwendung der Regeln für die Ableitung von Vorlagenargumenten aus dem Operanden seiner Rückgabeanweisung abgeleitet wird.

4) Wenn der deklarierte Typ der Variablen decltype (auto) ist, wird das Schlüsselwort auto durch den Ausdruck (oder die Ausdrucksliste) des Initialisierers ersetzt und der tatsächliche Typ anhand der Regeln für decltype abgeleitet.

5) Wenn der Rückgabetyp der Funktion als decltype (auto) deklariert ist, wird das Schlüsselwort auto durch den Operanden der return-Anweisung ersetzt und der tatsächliche Rückgabetyp anhand der Regeln für decltype abgeleitet.

6) Ein verschachtelter Namensbezeichner der Form auto :: ist ein Platzhalter, der durch einen Klassen- oder Aufzählungstyp ersetzt wird, der den Regeln für den Abzug von Platzhaltern mit eingeschränktem Typ folgt.

7) Eine Parameterdeklaration in einem Lambda-Ausdruck. (seit C ++ 14) Eine Funktionsparameterdeklaration. (Konzepte TS)

Hinweise Bis C ++ 11 hatte auto die Semantik eines Speicherdauerspezifizierers. Das Mischen von automatischen Variablen und Funktionen in einer Deklaration wie in auto f() -> int, i = 0;ist nicht zulässig.

Für weitere Informationen: http://en.cppreference.com/w/cpp/language/auto

Prathamesh bewusst
quelle
11

Diese Funktionalität war Ihr ganzes Leben lang nicht da. Es wird seit der Version 2010 in Visual Studio unterstützt. Es ist eine neue C ++ 11-Funktion, daher ist sie nicht nur für Visual Studio verfügbar und kann portabel sein. Die meisten Compiler unterstützen dies bereits.

R. Martinho Fernandes
quelle
3

Es geht nirgendwo hin ... es ist eine neue Standard-C ++ - Funktion in der Implementierung von C ++ 11. Obwohl es ein wunderbares Werkzeug ist, um Objektdeklarationen zu vereinfachen und die Syntax für bestimmte Aufrufparadigmen (dh bereichsbasierte for-Schleifen) zu bereinigen, sollten Sie es nicht überbeanspruchen / missbrauchen :-)

Jason
quelle
3

Das Schlüsselwort auto gibt an, dass der Typ der deklarierten Variablen automatisch von ihrem Initialisierer abgezogen wird. Wenn bei Funktionen der Rückgabetyp automatisch ist, wird dies zur Laufzeit durch den Ausdruck des Rückgabetyps ausgewertet.

Es kann sehr nützlich sein, wenn wir den Iterator verwenden müssen. Zum Beispiel für den folgenden Code können wir einfach das "Auto" verwenden, anstatt die gesamte Iteratorsyntax zu schreiben.

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

So können wir das Schlüsselwort "auto" verwenden

rahul goyal
quelle
0

Es ist magisch, weil es weniger Code für jeden Variablentyp schreiben muss, der an bestimmte Funktionen übergeben wird. Betrachten Sie eine Python-ähnliche print () -Funktion in ihrer C-Basis.

#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
quelle