2013-06-10 3 views
40

In C++ 11, kann ich einige Container wie so iterieren:C++ 11 bereichsbasierte for-Schleife Effizienz "const Auto & i" im Gegensatz zu "auto i"

for(auto i : vec){ 
    std::cout << i << std::endl; 
} 

Aber ich weiß, dass dies unnötig - unnötig, da ich nur die Werte von vec-drucken müssen - macht eine Kopie (EDIT: jedes Element) vec, so stattdessen konnte ich tun:

for(auto &i : vec){ 
    std::cout << i << std::endl; 
} 

Aber ich möchte sicherstellen, dass die Werte von vec durch const-Korrektheit nie geändert und bleiben, so kann ich tun:

for(const auto &i : vec){ 
    std::cout << i << std::endl; 
} 

Also meine Frage ist: Wenn ich nur zu Blick auf die Notwendigkeit Werte von einigen Behältern, würde nicht die allerletzte Schleife (const auto &i) immer wegen der erhöhten Effizienz bevorzugt werden, keine zusätzliche Kopie von (: jedes Element von) vec zu haben?

Ich habe ein Programm, das ich entwickle, in dem ich darüber nachdenke, diese Änderung durchgängig zu machen, da Effizienz entscheidend ist (der Grund, warum ich C++ an erster Stelle benutze).

+1

Ja, wenn Sie nur Lesezugriff auf ein Argument benötigen, sollte es durch 'auto const &' erfolgen, um eine unnötige Kopie zu vermeiden. – 0x499602D2

+2

Das "const" -Schlüsselwort macht Ihren Code nicht schneller, obwohl ... – Tim

+4

'für (auto i: vec)' keine zusätzliche Kopie des gesamten 'vec' erstellt, es kopiert jedes Element von' vec' in "ich". – Casey

Antwort

54

Ja. Aus dem gleichen Grund, wenn Sie 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". Wenn T ein grundlegender Typ (eingebaut) ist, werden Sie im Allgemeinen einfach zu const T (keine Referenz) zum Lesen zurückkehren, da eine Kopie billiger als Aliasing ist.


Ich habe ein Programm, das ich entwickeln werde, in dem ich in Anbetracht dieser Änderung im gesamten, da die Effizienz in es kritisch ist,

  1. nicht blind radikale Veränderungen machen Sie . Ein Arbeitsprogramm ist besser als ein schnelles, aber kaputtes Programm.
  2. Wie Sie durch Ihre Schleifen iterieren, wird wahrscheinlich keinen großen Unterschied machen; Sie schleifen aus einem bestimmten Grund, nicht wahr? Der Körper Ihrer Schleife wird viel wahrscheinlicher der Übeltäter sein.
  3. Wenn Effizienz entscheidend ist, möchten Sie einen Profiler verwenden, um herauszufinden, welche Teile des Programms sind tatsächlich langsam, anstatt an Teilen zu erraten, die langsam sein könnte. Siehe Nr. 2, warum Ihre Vermutung falsch sein könnte.
+0

"Kopie ist billiger als Aliasing" nur mit den meisten grundlegenden Typen, außer Verschieben Semantik kann nicht in der OP-Situation verwendet werden und da es T jeder Typ sein kann, wäre eine Referenz die richtige Wahl. – Tim

+1

"*" Kopie ist billiger als Aliasing "nur mit den meisten grundlegenden Arten *" Aus diesem Grund ist die erste Hälfte dieses Satzes gewidmet zu sagen, es gilt für grundlegende Arten ...? Wenn Sie den Typ nicht kennen, verwenden Sie den allgemeinen Fall. – GManNickG

+0

Entschuldigung, ich muss es gelesen haben. – Tim

0

Stellen Sie sich vor, wenn Ihr Vektor Strings enthält. Lange Saiten. 5000 lange Saiten. Kopiere sie unnötigerweise und du erhältst eine schön geschriebene for-Schleife, die furchtbar ineffizient ist.

Stellen Sie sicher, dass Ihr Code Ihrer Absicht entspricht. Wenn Sie keine Kopie innerhalb der Schleife benötigen, erstellen Sie keine Kopie.

Verwenden Sie eine Referenz & wie oben vorgeschlagen oder Iteratoren.