Gibt es einen Grund, das Schlüsselwort 'auto' in C ++ 03 zu verwenden?

84

Beachten Sie, dass diese Frage ursprünglich im Jahr 2009 gestellt wurde, bevor C ++ 11 ratifiziert wurde und bevor die Bedeutung des autoSchlüsselworts drastisch geändert wurde. Die Antworten beziehen sich nur auf die C ++ 03-Bedeutung von auto- das ist eine spezifizierte Speicherklasse - und nicht auf die C ++ 11-Bedeutung von auto- das ist die automatische Typableitung. Wenn Sie nach Ratschlägen zur Verwendung von C ++ 11 suchen auto, ist diese Frage für diese Frage nicht relevant.

Für die längste Zeit dachte ich, es gäbe keinen Grund, das staticSchlüsselwort in C zu verwenden, da Variablen, die außerhalb des Blockbereichs deklariert wurden, implizit global waren. Dann entdeckte ich, dass das Deklarieren einer Variablen als staticinnerhalb des Blockbereichs eine dauerhafte Dauer und das Deklarieren außerhalb des Blockbereichs (im Programmbereich) einen Dateibereich ergeben würde (auf den nur in dieser Kompilierungseinheit zugegriffen werden kann).

Ich habe also nur ein Schlüsselwort, das ich (vielleicht) noch nicht vollständig verstehe: Das autoSchlüsselwort. Gibt es eine andere Bedeutung als "lokale Variable"? Gibt es etwas, das nicht implizit für Sie erledigt wird, wo immer Sie es verwenden möchten? Wie verhält sich eine autoVariable im Programmumfang? Was ist mit einer static autoVariablen im Dateibereich? Hat dieses Schlüsselwort einen anderen Zweck als nur der Vollständigkeit halber?

Carson Myers
quelle

Antworten:

74

autoist ein Speicherklassen - Bezeichner, static, registerund externauch. Sie können nur eine dieser vier in einer Deklaration verwenden.

Lokale Variablen (ohne static) haben eine automatische Speicherdauer, dh sie leben vom Beginn ihrer Definition bis zum Ende ihres Blocks. Das automatische Vorstellen ist redundant, da dies ohnehin die Standardeinstellung ist.

Ich kenne keinen Grund, es in C ++ zu verwenden. In alten C-Versionen mit der impliziten int-Regel können Sie damit eine Variable deklarieren, wie in:

int main(void) { auto i = 1; }

Um es zu einer gültigen Syntax zu machen oder von einem Zuweisungsausdruck zu unterscheiden, falls dies iim Geltungsbereich liegt. Dies funktioniert jedoch in C ++ ohnehin nicht (Sie müssen einen Typ angeben). Lustigerweise schreibt der C ++ Standard:

Ein Objekt, das im Blockbereich ohne Speicherklassenspezifizierer deklariert oder als Funktionsparameter deklariert wurde, hat standardmäßig eine automatische Speicherdauer. [Hinweis: Daher ist der automatische Bezeichner fast immer redundant und wird nicht oft verwendet. Eine Verwendung von auto besteht darin, eine Deklarationsanweisung explizit von einer Ausdrucksanweisung (6.8) zu unterscheiden. - Endnote]

Dies bezieht sich auf das folgende Szenario, bei dem es sich entweder um eine Umwandlung von ato intoder um die Deklaration einer Variablen avom Typ intmit redundanten Klammern handeln kann a. Es wird immer als Erklärung angesehen, daher autowürde hier nichts Nützliches hinzugefügt, sondern für den Menschen. Andererseits wäre es für den Menschen besser, die überflüssigen Klammern zu entfernen a, würde ich sagen:

int(a);

Mit der neuen Bedeutung auto, mit C ++ 0x anzukommen, würde ich davon abraten, es mit der Bedeutung von C ++ 03 im Code zu verwenden.

Johannes Schaub - litb
quelle
4
C ++ - Compiler hatten oft implizite int für Rückgabewerte von Funktionen, damals in den ARM-Tagen vor dem Standard ... Vor dem REICH ...
Daniel Earwicker
1
Ich habe es nur als meine Art des Compilers erkannt, mir zu sagen, dass ich vergessen habe, eine Funktion vorwärts zu deklarieren. Es würde mir sagen, dass meine Verwendung einer Funktion sich von der Art und Weise unterschied, wie sie aufgrund des impliziten int deklariert wurde.
Carson Myers
29
Das Beste daran ist, dass Programmierer "auto" (vier Buchstaben) geschrieben haben, um sich vor dem Schreiben von "int" (drei Buchstaben) zu schützen.
Max Lybbert
30
@Max - hey, viele Leute sagen "double-u-double-u-double-u" als Abkürzung für "World Wide Web".
Daniel Earwicker
3
@smichak nein, "volatile" ist ein Typqualifizierer. Anstatt zu bestimmen, wo ein Wert gespeichert werden soll, ändert sich das Verhalten beim Schreiben und Lesen von Objekten des flüchtigen qualifizierten Typs. Es kann flüchtige qualifizierte Stapelvariablen (automatische Speicherklasse) sowie flüchtige qualifizierte statische Speicherdauervariablen (lokale 'statische' Speicherklasse, nicht lokale Variablen) geben. Abgesehen davon weiß ich nicht, ob "register volatile" eine gültige Kombination ist :)
Johannes Schaub - litb
86

Hat in C ++ 11 autoeine neue Bedeutung: Sie können den Typ einer Variablen automatisch ableiten.

Warum ist das jemals nützlich? Betrachten wir ein grundlegendes Beispiel:

std::list<int> a;
// fill in a
for (auto it = a.begin(); it != a.end(); ++it) {
  // Do stuff here
}

Das autodort erstellt einen Iterator vom Typ std::list<int>::iterator.

Dies kann das Lesen von sehr komplexem Code erheblich erleichtern.

Ein anderes Beispiel:

int x, y;
auto f = [&]{ x += y; };
f();
f();

Dort wurde der autoTyp abgeleitet, der zum Speichern eines Lambda-Ausdrucks in einer Variablen erforderlich ist. Wikipedia hat eine gute Berichterstattung zu diesem Thema.

std''OrgnlDave
quelle
4
Ich bin mir immer noch nicht sicher, ob dies eine großartige Verwendung von Auto ist. Code sollte leicht zu lesen und nicht leicht zu schreiben sein!
DanDan
38
Ich weiß nichts über dich, aber ich finde das viel einfacher zu lesen als Spam vom Typ Iterator.
Overv
17
Und wenn Sie sich für eine Resonanz entscheiden, die Klasse von list <int> in eine andere Klasse zu ändern, müssen Sie nicht nach jeder Iteratordeklaration suchen und diese ändern.
Roslav
2
@KarateSnowMachine: Wenn Sie die Konstante möchten, würden Sie "const auto" anstelle von "auto" verwenden.
Darth Happyface
4
@darth const auto it = a.begin();würde dir eine Konstante geben iterator, keine const_iterator. Sie könnten das Element noch ändern, aber ++itnicht kompilieren. Um eine zu bekommen const_iterator, würden Sie verwendenauto it = a.cbegin();
Fredoverflow
34

Das Schlüsselwort auto hat derzeit keinen Zweck. Sie haben genau Recht, dass nur die Standardspeicherklasse einer lokalen Variablen angepasst wird. Die wirklich nützliche Alternative ist static.

Es hat eine brandneue Bedeutung in C ++ 0x. Das gibt Ihnen eine Vorstellung davon, wie nutzlos es war!

Daniel Earwicker
quelle
1
Oh Mann, ist das jemals nutzlos? Ich mag die neue Bedeutung. Es macht einige Codes viel weniger ausführlich und redundant.
Carson Myers
Ja, wenn Sie das Äquivalent in C # verwendet haben, wird es wahrscheinlich einen großen Unterschied machen. Dies gilt insbesondere in C ++, wenn Sie Ausdrucksvorlagen verwenden, bei denen die Typen so komplex sind, dass sie niemals von Hand geschrieben werden sollten.
Daniel Earwicker
7

GCC wird speziell autofür verschachtelte Funktionen verwendet - siehe hier .

Wenn Sie eine verschachtelte Funktion haben, die Sie vor ihrer Definition aufrufen möchten, müssen Sie sie mit deklarieren auto.

qrdl
quelle
Dies ist eine großartige, wenn auch vom Compiler abhängige Implementierung von Auto. Vielen Dank für die Recherche :)
Carson Myers
3

"auto" soll den Compiler anweisen, selbst zu entscheiden, wo die Variable (Speicher oder Register) abgelegt werden soll. Sein Analogon ist "register", was den Compiler angeblich anweist, zu versuchen, es in einem Register zu halten. Moderne Compiler ignorieren beide, also sollten Sie auch.

TED
quelle
1
Nicht genau - wenn Sie es mit "register" deklarieren, lassen Compiler Sie den Address-of-Operator (& foo) nicht für die Variable verwenden, da er nirgendwo im Speicher vorhanden ist (und daher keine Adresse hat).
Tim
3

Ich verwende dieses Schlüsselwort, um explizit zu dokumentieren, wenn es für die Funktion kritisch ist, dass die Variable für stapelbasierte Prozessoren auf dem Stapel platziert wird. Diese Funktion kann erforderlich sein, wenn der Stapel geändert wird, bevor von einer Funktion (oder einer Interrupt-Serviceroutine) zurückgekehrt wird. In diesem Fall erkläre ich:

auto unsigned int auiStack[1];   //variable must be on stack

Und dann greife ich außerhalb der Variablen zu:

#define OFFSET_TO_RETURN_ADDRESS 8     //depends on compiler operation and current automatics
auiStack[OFFSET_TO_RETURN_ADDRESS] = alternate_return_address;

Das autoSchlüsselwort hilft also, die Absicht zu dokumentieren.

Luke
quelle
Ich gehe davon aus, dass dies nur eine Signalabsicht ist, da das Schlüsselwort die Stapelplatzierung nicht erzwingt, genauso wenig wie es einfach weglassen würde.
underscore_d
2

Laut Stroustrup hat die Verwendung von 'auto' in "The C Programming Language" (4. Ausgabe, C 11) folgende Hauptgründe (Abschnitt 2.2.2) (Stroustrup-Wörter werden zitiert):

1)

Die Definition hat einen großen Umfang, in dem wir den Typ für die Leser unseres Codes klar sichtbar machen möchten.

Mit 'auto' und dem notwendigen Initialisierer können wir den Variablentyp auf einen Blick erkennen!

2)

Wir möchten den Bereich oder die Genauigkeit der Variablen explizit angeben (z. B. double statt float).

Meiner Meinung nach ist ein Fall, der hierher passt, ungefähr so:

   double square(double d)
    {
        return d*d; 
    }

    int square(int d)
    {
        return d*d; 
    }

    auto a1 = square(3);

    cout << a1 << endl;

    a1 = square(3.3);

    cout << a1 << endl;

3)

Mit 'auto' vermeiden wir Redundanz und schreiben lange Typnamen.

Stellen Sie sich einen langen Typnamen aus einem Iterator mit Vorlagen vor:

(Code aus Abschnitt 6.3.6.1)

template<class T> void f1(vector<T>& arg) {
    for (typename vector<T>::iterator p = arg.begin(); p != arg.end();   p)
        *p = 7;

    for (auto p = arg.begin(); p != arg.end();   p)
        *p = 7;
}
wesley.mesquita
quelle
1

Im alten Compiler war auto eine Möglichkeit, eine lokale Variable überhaupt zu deklarieren. Sie können lokale Variablen in alten Compilern wie Turbo C nicht ohne das Schlüsselwort auto oder ähnliches deklarieren.

chaz
quelle
1

Die neue Bedeutung des Auto - Schlüsselwort in C ++ 0x ist sehr schön beschrieben von Microsofts Stephan T. Lavavej in einem frei sichtbaren / herunterladbare Video Vortrag über STL auf MSDN Channel 9 Website gefunden hier .

Die Vorlesung ist in ihrer Gesamtheit sehenswert, aber der Teil über das Auto-Schlüsselwort befindet sich ungefähr in der 29. Minute (ungefähr).

Sabuncu
quelle
0

Gibt es eine andere Bedeutung für "auto" als "lokale Variable"?

Nicht in C ++ 03.

Gibt es etwas, das nicht implizit für Sie erledigt wird, wo immer Sie es verwenden möchten?

Nichts in C ++ 03.

Wie verhält sich eine automatische Variable im Programmbereich? Was ist mit einer statischen automatischen Variablen im Dateibereich?

Schlüsselwort außerhalb eines Funktions- / Methodenkörpers nicht zulässig.

Hat dieses Schlüsselwort einen anderen Zweck [in C ++ 03] als nur der Vollständigkeit halber?

Überraschenderweise ja. Zu den C ++ - Entwurfskriterien gehörte ein hohes Maß an Abwärtskompatibilität mit C. C hatte dieses Schlüsselwort und es gab keinen wirklichen Grund, es zu verbieten oder seine Bedeutung in C ++ neu zu definieren. Der Zweck war also eine Inkompatibilität weniger mit C.

Hat dieses Schlüsselwort in C einen anderen Zweck als nur der Vollständigkeit halber?

Ich habe erst kürzlich eines gelernt: Die einfache Portierung alter Programme aus B. C entwickelte sich aus einer Sprache namens B, deren Syntax der von C ziemlich ähnlich war. B hatte jedoch keinerlei Typen. Die einzige Möglichkeit, eine Variable in B zu deklarieren, bestand darin, ihren Speichertyp ( autooder extern) anzugeben . So was:

auto i;

Diese Syntax funktioniert immer noch in C und entspricht

int i;

In C wird standardmäßig die Speicherklasse und standardmäßig autoder Typ verwendet int. Ich denke, dass jedes einzelne Programm, das aus B stammte und nach C portiert wurde auto, zu dieser Zeit buchstäblich voller Variablen war.

In C ++ 03 ist das implizite int des C-Stils nicht mehr zulässig, das nicht mehr genau nützliche autoSchlüsselwort wurde jedoch beibehalten, da im Gegensatz zum impliziten int keine Probleme mit der Syntax von C verursacht wurden.

Jirka Hanika
quelle