
Benutzer2052561
In C++11 kann ich so über einen Container iterieren:
for(auto i : vec){
std::cout << i << std::endl;
}
Aber ich weiß, dass dies unnötig – unnötigerweiseda muss ich nur drucken die Werte von vec
– erstellt eine Kopie von (BEARBEITEN: jedes Element von) vec
also könnte ich stattdessen Folgendes tun:
for(auto &i : vec){
std::cout << i << std::endl;
}
Aber ich möchte sicherstellen, dass die Werte von vec
werden nie geändert und halten sich an die Konstantenkorrektheit, also kann ich Folgendes tun:
for(const auto &i : vec){
std::cout << i << std::endl;
}
Meine Frage ist also: Wenn ich nur muss suchen würde bei den Werten einiger Container nicht die allerletzte Schleife (const auto &i
) immer bevorzugt werden, da es effizienter ist, keine zusätzliche Kopie von (BEARBEITEN: jedes Element von) vec
?
Ich habe ein Programm, das ich entwickle, in dem ich erwäge, diese Änderung durchgehend vorzunehmen, da die Effizienz entscheidend ist (der Grund, warum ich C++ an erster Stelle verwende).

GManNickG
Ja. Aus dem gleichen Grund, wenn Sie immer nur ein Argument lesen, machen Sie den Parameter const&
.
T // I'm copying this
T& // I'm modifying this
const T& // I'm reading this
Das sind Ihre “Standardwerte”. Wann T
ist ein grundlegender Typ (eingebaut), auf den Sie jedoch im Allgemeinen einfach zurückgreifen const T
(keine Referenz) zum Nachlesen, da eine Kopie billiger ist als Aliasing.
Ich habe ein Programm, das ich entwickle, bei dem ich erwäge, diese Änderung durchgehend vorzunehmen, da Effizienz entscheidend ist
- Nehmen Sie keine blinden Änderungen vor. Ein funktionierendes Programm ist besser als ein schnelles, aber kaputtes Programm.
- Wie Sie durch Ihre Schleifen iterieren, wird wahrscheinlich keinen großen Unterschied machen; Du loopst aus einem bestimmten Grund, nicht wahr? Der Körper Ihrer Schleife wird viel wahrscheinlicher der Schuldige sein.
- Wenn Effizienz entscheidend ist, möchten Sie a verwenden Profiler um herauszufinden, welche Teile Ihres Programms sind eigentlich langsam, anstatt Teile davon zu erraten könnte langsam sein. Siehe Nr. 2, warum Ihre Vermutung falsch sein könnte.
Haftungsausschluss: Im Allgemeinen ist der Unterschied zwischen auto
und auto&
ist subtil, teilweise eine Frage des Stils, manchmal aber auch eine Frage der Korrektheit. Ich werde hier nicht den allgemeinen Fall behandeln!
In einer bereichsbasierten for-Schleife ist der Unterschied zwischen
for (auto element : container) {}
und
for (auto& element_ref : container) {}
ist dass element
ist eine Kopie der Elemente in der container
während element_ref
ist ein Verweis auf die Elemente im Container.
Betrachten Sie dieses Beispiel, um den Unterschied in der Aktion zu sehen:
#include <iostream>
int main(void) {
int a[5] = { 23,443,16,49,66 };
for (auto i : a) i = 5;
for (const auto& i : a) std::cout << i << std::endl;
for (auto& i : a) i = 5;
for (const auto& i : a) std::cout << i << std::endl;
}
Es wird gedruckt
23
443
16
49
66
5
5
5
5
5
weil die erste Schleife mit Kopien der Array-Elemente arbeitet, während die zweite tatsächlich die Elemente im Array ändert.
Wenn Sie die Elemente nicht ändern möchten, dann a const auto&
ist besser geeignet, weil es das Kopieren der Elemente vermeidet (was teuer sein kann).
Stellen Sie sich vor, Ihr Vektor enthält Zeichenfolgen. Lange Saiten. 5000 lange Saiten. Wenn Sie sie unnötigerweise kopieren, erhalten Sie am Ende eine schön geschriebene for-Schleife, die schrecklich ineffizient ist.
Stellen Sie sicher, dass Ihr Code Ihrer Absicht folgt. Wenn Sie keine Kopie innerhalb der Schleife benötigen, erstellen Sie keine.
Verwenden Sie eine Referenz & wie oben vorgeschlagen oder Iteratoren.
10128600cookie-checkC++11 Range-basierte for-Loop-Effizienz „const auto &i“ versus „auto i“yes
Ja, wenn Sie nur Lesezugriff auf ein Argument benötigen, sollte es durchgehen
auto const&
um eine unnötige Kopie zu vermeiden.– David G
10. Juni 2013 um 20:33 Uhr
Das Schlüsselwort “const” macht Ihren Code jedoch nicht schneller …
– Tim
10. Juni 2013 um 20:35 Uhr
for (auto i : vec)
macht keine zusätzliche Kopie des Ganzenvec
es kopiert jeden Element vonvec
hineini
.– Casey
10. Juni 2013 um 20:59 Uhr
@Casey Ich verstehe. Bei jeder neuen Iteration wird also die vorherige Kopie gelöscht, richtig?
– Benutzer2052561
10. Juni 2013 um 21:07 Uhr
@ user2052561 – nicht gelöscht, aber zerstört.
– Peter Becker
10. Juni 2013 um 23:19 Uhr