Beim Lesen einiger Beispiele für bereichsbasierte Schleifen schlagen sie zwei Hauptmethoden vor: 1 , 2 , 3 , 4
std::vector<MyClass> vec;
for (auto &x : vec)
{
// x is a reference to an item of vec
// We can change vec's items by changing x
}
oder
for (auto x : vec)
{
// Value of x is copied from an item of vec
// We can not change vec's items by changing x
}
Gut.
Wenn wir keine vec
Elemente ändern müssen, empfehlen IMO, Beispiele, die zweite Version (nach Wert) zu verwenden. Warum sie nicht etwas vorschlagen, auf das const
verwiesen wird (Zumindest habe ich keinen direkten Vorschlag gefunden):
for (auto const &x : vec) // <-- see const keyword
{
// x is a reference to an const item of vec
// We can not change vec's items by changing x
}
Ist es nicht besser Vermeidet es nicht eine redundante Kopie in jeder Iteration, während es eine ist const
?
const auto &x
dies Ihrer dritten Wahl entspricht.auto&&
Wenn Sie keine unnötige Kopie erstellen möchten und es Ihnen egal ist, ob Sie sie ändern oder nicht, und Sie einfach arbeiten möchten.const
sicher verwenden. Ob es jedoch wäreauto const &
oderauto const
wenig Unterschied hat. Ich würde mich dafür entscheidenauto const &
, konsequenter zu sein.Wenn Sie ein
std::vector<int>
oder habenstd::vector<double>
, ist es in Ordnung,auto
(mit Wertkopie) anstelle von zu verwendenconst auto&
, da das Kopieren einesint
oder einesdouble
billig ist:Wenn Sie jedoch eine haben
std::vector<MyClass>
, bei der esMyClass
sich um eine nicht triviale Kopiersemantik handelt (z. B.std::string
eine komplexe benutzerdefinierte Klasse usw.), würde ich die Verwendung empfehlenconst auto&
, um Deep-Copies zu vermeiden :quelle
Dann machen sie einen falschen Vorschlag.
Weil sie einen falschen Vorschlag machen :-) Was Sie erwähnen, ist richtig. Wenn Sie nur ein Objekt beobachten möchten, müssen Sie keine Kopie erstellen und es muss kein
const
Verweis darauf vorhanden sein.BEARBEITEN:
Ich sehe, dass die Referenzen, die Sie alle verknüpfen, Beispiele für das Iterieren über einen Wertebereich
int
oder einen anderen grundlegenden Datentyp liefern. In diesem Fallint
ist das Erstellen einer Kopie im Grunde genommen gleichbedeutend mit einer Beobachtung (wenn nicht sogar effizienter als diese) , da das Kopieren von nicht teuer istconst &
.Dies ist jedoch bei benutzerdefinierten Typen im Allgemeinen nicht der Fall. Das Kopieren von UDTs kann teuer sein. Wenn Sie keinen Grund haben, eine Kopie zu erstellen (z. B. das abgerufene Objekt zu ändern, ohne das Original zu ändern), ist es vorzuziehen, a zu verwenden
const &
.quelle
Ich werde hier das Gegenteil sagen und sagen, dass es
auto const &
in einem Bereich, der auf einer Schleife basiert, keine Notwendigkeit gibt . Sagen Sie mir, wenn Sie die folgende Funktion für dumm halten (nicht in ihrem Zweck, sondern in der Art und Weise, wie sie geschrieben ist):Hier hat der Autor einen konstanten Verweis erstellt,
v
der für alle Operationen verwendet werden soll, die v nicht ändern. Dies ist meiner Meinung nach albern, und das gleiche Argument kann für die Verwendungauto const &
als Variable in einem Bereich verwendet werden, der auf einer Schleife basiert, anstatt nurauto &
.quelle
const_iterator
in einer for-Schleife dagegen argumentieren würden ? Wie stellen Sie sicher, dass Sie die Originalelemente aus einem Container nicht ändern, wenn Sie darüber iterieren?const_iterator
? Lassen Sie mich raten, der Container, über den Sie iterieren, istconst
. Aber warum ist es soconst
? Irgendwo verwenden Sie,const
um sicherzustellen, was?const
liegt in den Vorteilen der Verwendung vonprivate
/protected
in Klassen. Es vermeidet weitere Fehler.v
, wäre die Implementierung IMO in Ordnung. Und wenn die Schleife niemals die Objekte ändert, durch die sie iteriert, erscheint es mir richtig, einen Verweis auf zu habenconst
. Ich verstehe deinen Standpunkt. Meins ist, dass die Schleife eine Codeeinheit darstellt, ähnlich wie die Funktion, und innerhalb dieser Einheit gibt es keine Anweisung, die den Wert ändern muss. Daher können Sie die gesamte Einheit wieconst
bei einerconst
Mitgliedsfunktion als "kennzeichnen" .const &
dass Range-Based dumm ist, weil Sie ein irrelevantes imaginäres Beispiel eines imaginären Programmierers geschrieben haben, der etwas Dummes mit Lebenslaufqualifikation gemacht hat? ... OK dann