Um es zu testen, habe ich drei Quelldateien erstellt:
%Vor% Nach dem Kompilieren mit g++ -S -O3
, GCC 4.6.1, stelle ich fest, dass Version 2 und 3 eine identische Assembly erzeugen, und Version 1 unterscheidet sich nur in einer Anweisung, cmpl %eax, %esi
vs cmpl %esi, %eax
.
Also, wählen Sie und verwenden Sie, was Ihrem Stil entspricht. Präfix inkrement ++it
ist wahrscheinlich am besten, weil es Ihre Anforderungen am genauesten ausdrückt, aber lassen Sie sich nicht davon abhalten.
it++
gibt eine Kopie des vorherigen Iterators zurück. Da dieser Iterator nicht verwendet wird, ist dies verschwenderisch. ++it
gibt einen Verweis auf den inkrementierten Iterator zurück, wobei die Kopie vermieden wird.
Bitte sehen Sie Frage 13.15 für eine ausführlichere Erklärung.
Es gibt einen leichten Leistungsvorteil bei der Verwendung von Pre-Increment-Operatoren gegenüber Post -inkrementelle Operatoren. Beim Einrichten von Schleifen, die Iteratoren verwenden, sollten Sie Vorinkremente verwenden:
%Vor%Der Grund kommt zum Vorschein, wenn Sie darüber nachdenken, wie beide Operatoren normalerweise implementiert werden. Das Pre-Inkrement ist ziemlich einfach. Damit das Post-Inkrement funktioniert, müssen Sie zunächst eine Kopie des Objekts erstellen, das tatsächliche Inkrement für das ursprüngliche Objekt ausführen und dann die Kopie zurückgeben:
%Vor%Wie Sie sehen, beinhaltet die Post-Inkrement-Implementierung zwei zusätzliche Kopiervorgänge. Dies kann ziemlich teuer sein, wenn das betreffende Objekt sperrig ist. Abgesehen davon, können einige Compiler intelligent genug sein, um durch die Optimierung mit einem einzigen Kopiervorgang davonzukommen. Der Punkt ist, dass ein Post-Inkrement normalerweise mehr Arbeit erfordert als ein Pre-Inkrement und daher ist es ratsam, sich daran zu gewöhnen, Ihre "++" s vor Ihren Iteratoren und nicht danach zu setzen.
(1) Guthaben auf der verlinkten Website.
Aus logischer Sicht - es ist das gleiche und es ist nicht wichtig hier .
Warum das Präfix eins verwendet wird - weil es schneller ist - es ändert den Iterator und gibt seinen Wert zurück, während das Postfix temp-Objekt erstellt, den aktuellen Iterator inkrementiert und dann das temp-Objekt zurückgibt (Kopie desselben Iterators vor dem Inkrementieren) ). Da niemand dieses temporäre Objekt hier beobachtet (den Rückgabewert), ist es (logisch) dasselbe.
Es gibt eine ziemlich große Chance, dass der Compiler das optimiert.
Außerdem sollte dies für beliebige -Typen überhaupt so sein. Aber es sollte nur sein. Da jeder operator++
- den Postfix und das Präfix - überladen kann, können sie Nebenwirkungen und ein anderes Verhalten haben.
Nun, das ist eine schreckliche Sache, aber immer noch möglich.
Wie andere Antworten gesagt haben, bevorzugen Sie es, wenn es nicht im Kontext funktioniert. Bei der Iteration über kleine Behälter macht dies kaum einen Unterschied (oder keinen Unterschied, wenn der Compiler sie optimiert), aber bei großen Behältern kann es einen Unterschied machen, weil die Kosten für das Erstellen einer Kopie eingespart werden.
Es stimmt, dass Sie in Ihrem spezifischen Kontext wissen, dass der Typ klein genug ist, damit Sie sich keine Sorgen machen müssen. Aber später kann jemand anderes in Ihrem Team den Inhalt des Containers dahin ändern, wo es wichtig wäre. Plus, ich denke, es ist besser, sich in eine gute Angewohnheit zu bringen, und nur nach-erhöhen, wenn Sie wissen, dass Sie müssen.