it-swarm.com.de

Sollte ich die neue C ++ 11-Funktion "Auto" verwenden, insbesondere in Schleifen?

Welche Vor- und Nachteile hat die Verwendung des Schlüsselworts auto, insbesondere in for-Schleifen?

for(std::vector<T>::iterator it = x.begin(); it != x.end(); it++ )
{
   it->something();
}

for(std::map<T>::iterator it = x.begin(); it != x.end(); it++ )
{
   it->second->something();
}

for(auto it = x.begin(); it != x.end(); it++ )
{
   it->??
}

Wenn Sie nicht wissen, ob Sie einen Iterator für eine Karte oder einen Vektor haben, wissen Sie anscheinend nicht, ob Sie first oder second verwenden oder einfach direkt auf die Eigenschaften des Objekts zugreifen sollen ?

Dies erinnert mich an die C # -Debatte über die Verwendung des Schlüsselworts var. Der Eindruck, den ich bisher habe, ist, dass die Leute in der C++ - Welt bereit sind, das Schlüsselwort auto mit weniger Kampf als var in der C # -Welt zu übernehmen. Für mich ist mein erster Instinkt, dass ich den Typ der Variablen gerne kenne, damit ich weiß, welche Operationen ich erwarten kann, um sie auszuführen.

20
User

Die Motivationen in C++ sind extremer, da Typen aufgrund von Metaprogrammierung und anderen Dingen erheblich komplizierter und komplexer werden können als C # -Typen. auto ist schneller zu schreiben und zu lesen und flexibler/wartbarer als ein expliziter Typ. Ich meine, willst du anfangen zu tippen?

boost::multi_map<NodeType, indexed_by<ordered_unique<identity<NodeType>>, hashed_non_unique<identity<NodeType>, custom_hasher>>::iterator_type<0> it

Das ist nicht einmal der volle Typ. Ich habe ein paar Vorlagenargumente verpasst.

40
DeadMG

In Ihrem Beispiel:

for(auto it = x.begin(); it != x.end(); i++)
{
  it->??
}

es muss eine Deklaration für x sichtbar sein. Daher sollte der Typ von it offensichtlich sein. Wenn der Typ von x nicht offensichtlich ist, ist die Methode zu lang oder die Klasse zu groß.

28
kevin cline

Einspruch ! Geladene Frage.

Können Sie mir erklären, warum der dritte Code ?? Enthält, der erste und der zweite jedoch nicht? Aus Gründen der Fairness lautet Ihr Code muss wie folgt:

for(std::vector<T>::iterator it = x.begin(); it != x.end(); i++)
{
   it->???
}

for(std::map<T>::iterator it = x.begin(); it != x.end(); i++)
{
   it->second->???
}

Dort. Das gleiche Problem, obwohl Sie auto nicht verwendet haben.

In allen Fällen ist die Antwort dieselbe: Kontext ist wichtig . Sie können nicht sinnvoll über einen einzelnen Code sprechen. Selbst wenn Sie keine Vorlagen, sondern einen konkreten Typ verwendet hätten, hätte dies das Problem nur an einen anderen Ort verschoben, da der Leser Ihres Codes über die Deklaration dieses Typs Bescheid wissen müsste.

Wenn die Verwendung von auto in solchen Situationen Ihren Code unlesbar macht, sollten Sie dies als Warnzeichen dafür behandeln, dass etwas mit Ihrem Code-Design nicht stimmt. Natürlich gibt es Fälle, in denen Details auf niedriger Ebene wichtig sind (z. B. beim Umgang mit Bitoperationen oder Legacy-APIs). In diesen Fällen kann ein expliziter Typ die Lesbarkeit verbessern. Aber im Allgemeinen - nein.

In Bezug auf var (da Sie es ausdrücklich erwähnt haben) gibt es auch ein großer Konsens in der C # -Community für mit var. Argumente gegen seine Verwendung sind im Allgemeinen auf Irrtümern aufgebaut .

14
Konrad Rudolph

PROFI

Dein Code :

for(std::vector<T>::iterator it = x.begin(); it != x.end(); i++)

wird aufgrund des vorlagenabhängigen Namens nicht kompiliert.

Dies ist die richtige Syntax:

for( typename std::vector<T>::iterator it = x.begin(); it != x.end(); i++)

Schauen Sie nun, wie lang die Typdeklaration ist. Dies erklärt, warum das Schlüsselwort auto eingeführt wurde. Diese :

for( auto it = x.begin(); it != x.end(); i++)

ist prägnanter. Das ist also ein Profi.


CON

Du musst ein bisschen vorsichtig sein. Mit dem Schlüsselwort auto erhalten Sie den von Ihnen deklarierten Typ.

Beispielsweise :

std::vector< int > v{ 1, 2, 3, 4 };
for ( auto it : v )
{
  ++ it;   // ops modifying copies of vector's elements
}

vs.

std::vector< int > v{ 1, 2, 3, 4 };
for ( auto & it : v )   // mind the reference
{
  ++ it;   // ok, vector's elements modified
}

Abschließend: Ja, Sie sollten es, aber nicht überbeanspruchen. Einige Leute neigen dazu, es zu oft zu benutzen und Auto überall zu platzieren, wie im nächsten Beispiel:

auto i = 0;

vs.

int i = 0;
11
BЈовић

Ja du solltest! auto löscht den Typ nicht; Selbst wenn Sie "nicht wissen", was x.begin() ist, weiß der Compiler und meldet einen Fehler, wenn Sie versuchen, den Typ falsch zu verwenden. Es ist auch nicht ungewöhnlich, map mit einem vector<pair<Key,Value>> Zu emulieren, sodass der Code, der auto verwendet, für beide Wörterbuchdarstellungen funktioniert.

6
zvrba

Ja, Sie sollten auto als Standardregel verwenden. Es hat rohe Vorteile gegenüber der expliziten Angabe des Typs:

  • Sie müssen keine Dinge eingeben, die dem Compiler bereits bekannt sind.
  • Dadurch wird der Variablentyp jeder Änderung der Rückgabewerttypen "folgen".
  • Auf diese Weise wird stille Einführung impliziter Konvertierungen und Slicing bei der Initialisierung lokaler Variablen verhindert.
  • Einige explizite Typberechnungen in Vorlagen sind nicht mehr erforderlich.
  • Die Benennung von Rückgabetypen mit langen Namen entfällt. (diejenigen, die Sie aus der Compiler-Diagnose kopieren und einfügen)

Hier haben Sie die Wahl. Es gibt auch Fälle, in denen Sie keine Wahl haben:

  • Es erlaubt die Deklaration von Variablen unaussprechlicher Typen, wie der Typ eines Lambda.

Vorausgesetzt, Sie wissen genau, was auto tut, hat es keine Nachteile.

4