
masud
Beim Lesen einiger Beispiele für bereichsbasierte Schleifen schlagen sie zwei Hauptwege 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
}
Brunnen.
Wenn wir keine Veränderung brauchen vec
Elemente, IMO, Beispiele schlagen vor, die zweite Version (nach Wert) zu verwenden. Warum sie nicht etwas vorschlagen, was const
Referenzen (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 sich um eine const
?

Nawaz
Wenn Sie die Artikel nicht so gut ändern möchten vermeiden dann Kopien machen auto const &
ist die richtige Wahl:
for (auto const &x : vec)
Wer auch immer Ihnen vorschlägt, zu verwenden auto &
ist falsch. Ignoriere sie.
Hier ist eine Zusammenfassung:
- Wählen
auto x
wenn Sie mit Kopien arbeiten möchten.
- Wählen
auto &x
wenn Sie mit Originalartikeln arbeiten und diese modifizieren können.
- Wählen
auto const &x
wenn Sie mit Originalelementen arbeiten möchten und diese nicht ändern.

Herr C64
Wenn Sie eine haben std::vector<int>
oder std::vector<double>
dann ist es gut zu verwenden auto
(mit Wert kopieren) statt const auto&
seit dem Kopieren eines int
oder ein double
ist günstig:
for (auto x : vec)
....
Aber wenn Sie eine haben std::vector<MyClass>
wo MyClass
hat eine nicht-triviale Kopiersemantik (z std::string
eine komplexe benutzerdefinierte Klasse usw.), dann würde ich die Verwendung vorschlagen const auto&
um tiefe Kopien zu vermeiden:
for (const auto & x : vec)
....

Andy Prowl
Wenn wir keine Veränderung brauchen vec
Elemente, Beispiele schlagen vor, die erste Version zu verwenden.
Dann geben sie einen falschen Vorschlag.
Warum sie nicht etwas vorschlagen, das Referenzen enthält
Weil sie einen falschen Vorschlag machen 🙂 Was Sie erwähnen, ist richtig. Wenn Sie nur wollen beobachten B. ein Objekt, ist es nicht erforderlich, eine Kopie zu erstellen, und es besteht keine Notwendigkeit, ein Nicht-const
Verweis darauf.
BEARBEITEN:
Ich sehe, dass die Referenzen, die Sie verlinken, alle Beispiele für die Iteration über eine Reihe von bieten int
Werte oder ein anderer grundlegender Datentyp. In diesem Fall, seit dem Kopieren einer int
ist nicht teuer, das Erstellen einer Kopie ist im Grunde gleichbedeutend (wenn nicht effizienter als) mit einer Beobachtung const &
.
Bei benutzerdefinierten Typen ist dies jedoch im Allgemeinen nicht der Fall. Das Kopieren von UDTs kann teuer sein, und wenn Sie keinen Grund haben, eine Kopie zu erstellen (z. B. das abgerufene Objekt zu ändern, ohne das ursprüngliche zu ändern), verwenden Sie vorzugsweise a const &
.
Ich werde hier widersprechen und sagen, dass es keine Notwendigkeit gibt auto const &
in einem Bereich basierend auf einer for-Schleife. Sagen Sie mir, ob Sie die folgende Funktion für dumm halten (nicht in ihrem Zweck, aber in der Art, wie sie geschrieben ist):
long long SafePop(std::vector<uint32_t>& v)
{
auto const& cv = v;
long long n = -1;
if (!cv.empty())
{
n = cv.back();
v.pop_back();
}
return n;
}
Hier hat der Autor einen const-Verweis auf erstellt v
für alle Operationen zu verwenden, die v nicht ändern. Das ist meiner Meinung nach albern, und das gleiche Argument kann für die Verwendung angeführt werden auto const &
als Variable in einem Bereich basierend auf for-Schleife statt nur auto &
.

rnd_nr_gen
würde ich in Betracht ziehen
for (auto&& o : range_expr) { ...}
oder
for (auto&& o : std::as_const(range_expr)) { ...}
es funktioniert immer.
und hüte dich vor möglich Temporärer Bereichsausdruck Tücken.
In C++20 haben Sie so etwas wie
for (T thing = foo(); auto& x : thing.items()) { /* ... */ }
9881100cookie-checkBereichsbasierte Schleife: Element nach Wert oder Verweis auf const abrufen?yes