Was ist der Vorteil der Verwendung von forwarding-Referenzen in range-basierte for-Schleifen?
const auto&
würde genügen, wenn ich möchte nur-lese-Operationen. Ich habe allerdings stieß in
for (auto&& e : v) //v is non-const
ein paar mal vor kurzem. Das macht mich Frage mich:
Ist es möglich, dass in einigen obskuren Ecke Fälle gibt es einige performance-Vorteil in der Verwendung von forwarding-Referenzen im Vergleich zu auto&
oder const auto&
?
(shared_ptr
ist ein Verdächtiger für die obskuren Ecke Fälle)
Update
Zwei Beispiele, die ich gefunden habe in meinen Favoriten:
Jeder Nachteil der Verwendung von const-Referenz bei der Iteration über die grundlegenden Typen?
Kann ich problemlos Durchlaufen, die Werte einer map mit einem range-basierte for-Schleife?
Bitte konzentrieren sich auf die Frage: warum würde ich wollen, verwenden Sie den auto&& in die range-basierte for-Schleifen?
- Tun Sie wirklich sehen, dass es "oft"?
- Ich bin mir nicht sicher, es gibt genug Kontext, in Ihrer Frage für mich um zu Messen, wie "verrückt" es ist, wo Sie sind, es zu sehen.
- Lange Rede, kurzer Sinn: warum würde ich wollen, verwenden Sie
auto&&
im range-basierte for-Schleifen?
Du musst angemeldet sein, um einen Kommentar abzugeben.
Der einzige Vorteil, den ich sehen kann, ist, wenn die Sequenz iterator liefert eine proxy-Referenz, und Sie müssen auf die Referenz in einer nicht-const Weg. Zum Beispiel:
Diese nicht kompilieren, da rvalue
vector<bool>::reference
zurückgegeben, die von deriterator
nicht eine Bindung an eine nicht-const lvalue reference. Aber dies funktioniert:Alle, die being said, ich würde nicht code dieser Art, es sei denn, Sie wussten, dass Sie benötigt, um zu erfüllen, solch ein Anwendungsfall. I. e. Würde ich nicht tun dies unentgeltlich, weil es hat dazu führen, Menschen zu Fragen, was du vorhast. Und wenn ich es tun, es würde nicht Schaden, um einen Kommentar, warum:
Bearbeiten
Diesem letzten Fall der mine sollte wirklich eine Vorlage, um Sinn zu machen. Wenn Sie wissen, die Schleife ist immer Umgang mit einem proxy-Referenz, dann
auto
funktionieren würde, sowieauto&&
. Aber wenn die Schleife war manchmal die Verarbeitung von nicht-proxy-Referenzen und manchmal proxy-Referenzen, dann denke ichauto&&
wäre die Lösung der Wahl.for
zu bevorzugenT::const_iterator
? Ich glaubebegin()
undend()
verwendet werden. Scheint ein bisschen wie ein versehen, außer der, die Sie verwenden können rvalue Referenzen. Also ja vielleicht ist das die Antwort.const auto&
wenn ich will, dass der compiler helfen Sie mir zu überprüfen, dass ich nicht versehentlich ändern Sie die Elemente in der Sequenz.for(auto& e : as_const(v)) ...
.const T::iterator
ist nichtT::const_iterator
, richtig? d.h. nicht, dass tatsächlich in diesem Fall? Ich nehme an, das ist eine andere Frage. Sieht aus wie "ja", aber ich weiß nicht, warum.auto&&
im generischen code wo muss ich zum ändern der Elemente der Sequenz. Wenn ich nicht, ich werde nur stickauto const&
.begin
, die überlastet ist aufconst
.auto&& e
eine rvalue ist und deshalb auch nicht möglich, zugeordnet werden? es ist buchstäblich, die auf der linken Seite..&&&
?auto&
inauto&&
hinter unserem Rücken?Mit
auto&&
oder universal-Referenzen mit einem range-basiertefor
-Schleife hat den Vorteil, dass Sie erfasst, was Sie bekommen. Für die meisten Arten von Iteratoren werden Sie wahrscheinlich entweder eineT&
oder eineT const&
für irgendeine ArtT
. Der interessante Fall ist, wo die Dereferenzierung einen iterator liefert einen temporären: C++ 2011 lockerte Anforderungen und Iteratoren sind nicht unbedingt erforderlich, um Ertrag ein lvalue. Die Verwendung von universal-Referenzen entspricht das argument der Weiterleitung instd::for_each()
:Die Funktion Objekt
f
behandeln könnenT&
,T const&
, undT
anders. Warum sollte der Körper eines range-basiertefor
-Schleife anders sein? Natürlich, um tatsächlich den Vorteil ableiten, die die Art der Nutzung von universal Verweise müssten Sie passieren Ihnen auf dem sinngemäß:Natürlich mit
std::forward()
bedeutet, dass Sie akzeptieren alle zurückgegebenen Werte bewegt werden, aus. Ob Objekte wie das macht viel Sinn in der nicht-template-code, weiß ich nicht (noch nicht?). Ich kann mir vorstellen, dass die Verwendung von universal-Referenzen bieten können weitere Informationen an den compiler, das Richtige zu tun. In der Vorlagen-code bleibt es aus für die Entscheidung auf das, was passieren soll mit den Objekten.Ich praktisch immer verwenden
auto&&
. Warum gebissen durch eine Kante, wenn Sie nicht müssen? Es ist kürzer, um zu geben, und ich finde einfach es mehr... transparent. Wenn Sieauto&& x
, dann wissen Sie, dassx
ist genau*it
jeder Zeit.const
-ness mitauto&&
wennconst auto&
genügt. Die Frage fragt nach der Ecke Fälle, wo ich kann, gebissen zu werden. Was sind die Ausnahmefälle, die nicht erwähnt wurden von Dietmar oder Howard noch?auto&&
. Wenn der Typ, den Sie erfassen sollte verschoben werden in den Körper der Schleife (zum Beispiel), und wird sich zu einem späteren Zeitpunkt, damit es behebt einenconst&
geben, Ihr code wird automatisch weiter funktionieren, aber Ihre Bewegungen werden kommen Kopien. Dieser code wird sehr trügerisch sein. Wenn du allerdings explizit die Art als r-value-Referenz, wer verändert die container geben wird, erhalten Sie einen Kompilierungsfehler, da Sie wirklich, wirklich wollte diese Objekte verschoben und nicht kopiert...for (std::decay_t<decltype(*v.begin())>&& e: v)
? Ich denke, es gibt einen besseren Weg ...auto&&
geben wird, eine "universal-Referenz", also alles andere als, die erhalten Sie einen spezifischeren Typ. Wennv
wird davon ausgegangen, dass einvector
Sie tun konntedecltype(v)::value_type&&
, das ist, was ich nehme an, Sie wollten durch die Einnahme das Ergebnis deroperator*
auf einen iterator geben. Sie können auchdecltype(begin(v))::value_type&&
zu überprüfen, die iterator-Typen anstelle des Containers. Wenn wir so wenig Einblick in die Art, obwohl, wir könnten es ein wenig klarer, nur mitauto&&
...