Ich lerne gerade C ++ und habe vor einiger Zeit etwas über die Inkrementierung gelernt. Ich weiß, dass Sie "++ x" verwenden können, um die Inkrementierung vorher vorzunehmen, und "x ++", um sie danach durchzuführen.
Trotzdem weiß ich wirklich nicht, wann ich eines der beiden verwenden soll ... Ich habe "++ x" nie wirklich verwendet und die Dinge haben bisher immer gut funktioniert - also wann sollte ich es verwenden?
Beispiel: Wann ist es in einer for-Schleife vorzuziehen, "++ x" zu verwenden?
Könnte jemand auch genau erklären, wie die verschiedenen Inkrementierungen (oder Dekrementierungen) funktionieren? Ich würde dies sehr begrüssen.
quelle
x++
ist es ein Wert mit dem Wertx
vor dem Inkrement,x++
ein Wert mit dem Wertx
nach dem Inkrement. Keiner der Ausdrücke garantiert, wenn der tatsächlich inkrementierte Wert wieder in x gespeichert wird. Es wird nur garantiert, dass dies vor dem nächsten Sequenzpunkt geschieht. 'nach der Verarbeitung der aktuellen Anweisung' ist nicht genau, da einige Ausdrücke Sequenzpunkte haben und einige Anweisungen zusammengesetzte Anweisungen sind.Scott Meyers fordert Sie auf, das Präfix zu bevorzugen, außer in Fällen, in denen die Logik vorschreibt, dass das Postfix angemessen ist.
"Effective C ++" Punkt 6 - das ist ausreichend Autorität für mich.
Für diejenigen, die das Buch nicht besitzen, sind hier die relevanten Zitate. Ab Seite 32:
Und auf Seite 34:
quelle
i++
oder++i
der generierte Code ist der gleiche.++x
undx++
tatsächlich von Bedeutung sind, ist es viel wichtiger, dass Sie tatsächlich einen Compiler verwenden, der beide Versionen unabhängig von der Version vollständig und ordnungsgemäß optimieren kann Kontext. "Da ich diesen beschissenen alten Hammer benutze, kann ich Nägel nur in einem Winkel von 43,7 Grad einschlagen" ist ein schlechtes Argument für den Bau eines Hauses, indem Nägel in nur 43,7 Grad eingeschlagen werden. Verwenden Sie ein besseres Werkzeug.Aus der Referenz beim Inkrementieren von Iteratoren:
Durch die Vorinkrementierung wird das temporäre Objekt nicht generiert. Dies kann einen erheblichen Unterschied machen, wenn die Erstellung Ihres Objekts teuer ist.
quelle
Ich möchte nur bemerken, dass der geneatisierte Code derselbe ist, wenn Sie eine Inkrementierung vor / nach der Inkrementierung verwenden, bei der die Semantik (von vor / nach) keine Rolle spielt.
Beispiel:
pre.cpp:
post.cpp:
_
quelle
std::map::iterator
? Natürlich sind die beiden Operatoren dort unterschiedlich, aber ich bin gespannt, ob der Compiler das Postfix auf das Präfix optimieren wird, wenn das Ergebnis nicht verwendet wird. Ich denke nicht, dass es erlaubt ist - da die Postfix-Version Nebenwirkungen enthalten könnte.Das Wichtigste ist, dass x ++ den Wert zurückgeben muss, bevor das Inkrement tatsächlich stattgefunden hat. Daher muss eine temporäre Kopie des Objekts erstellt werden (Pre-Inkrement). Dies ist weniger effizient als ++ x, das direkt inkrementiert und zurückgegeben wird.
Eine andere erwähnenswerte Sache ist jedoch, dass die meisten Compiler in der Lage sein werden, solche unnötigen Dinge zu optimieren, wenn dies möglich ist. Beispielsweise führen beide Optionen hier zu demselben Code:
quelle
Ich stimme @BeowulfOF zu, obwohl ich aus Gründen der Klarheit immer empfehlen würde, die Aussagen so aufzuteilen, dass die Logik absolut klar ist, dh:
oder
Meine Antwort lautet also: Wenn Sie klaren Code schreiben, sollte dies selten eine Rolle spielen (und wenn es darauf ankommt, ist Ihr Code wahrscheinlich nicht klar genug).
quelle
Ich wollte nur noch einmal betonen, dass ++ x voraussichtlich schneller als x ++ ist (insbesondere wenn x ein Objekt eines beliebigen Typs ist). Daher sollte ++ x verwendet werden, sofern dies nicht aus logischen Gründen erforderlich ist.
quelle
Sie haben den Unterschied richtig erklärt. Es hängt nur davon ab, ob x vor jedem Durchlauf einer Schleife oder danach inkrementiert werden soll. Es hängt von Ihrer Programmlogik ab, was angemessen ist.
Ein wichtiger Unterschied beim Umgang mit STL-Iteratoren (die auch diese Operatoren implementieren) besteht darin, dass ++ eine Kopie des Objekts erstellt, auf das der Iterator zeigt, diese dann inkrementiert und dann zurückgibt. ++ Es führt andererseits zuerst das Inkrement durch und gibt dann einen Verweis auf das Objekt zurück, auf das der Iterator jetzt zeigt. Dies ist meistens nur relevant, wenn jede Leistung zählt oder wenn Sie Ihren eigenen STL-Iterator implementieren.
Bearbeiten: Die Verwechslung von Präfix- und Suffixnotation wurde behoben
quelle
Beispiel 1:
Wenn mehrere Werte mit << unter Verwendung von cout kaskadiert werden, finden Berechnungen (falls vorhanden) von rechts nach links statt, der Druck erfolgt jedoch von links nach rechts, z. B. (wenn val anfänglich 10).
wird in ergeben
Beispiel 2:
Wenn in Turbo C ++ mehrere Vorkommen von ++ oder (in irgendeiner Form) in einem Ausdruck gefunden werden, werden zuerst alle Präfixformulare berechnet, dann wird der Ausdruck ausgewertet und schließlich werden Postfixformulare berechnet, z.
Es wird in Turbo C ++ ausgegeben
Während es im modernen Compiler ausgegeben wird (weil sie die Regeln streng befolgen)
Ausdrücke variieren von Compiler zu Compiler.
quelle
Das Verständnis der Sprachsyntax ist wichtig, wenn Sie die Klarheit des Codes berücksichtigen möchten. Kopieren Sie eine Zeichenfolge, beispielsweise mit Post-Inkrement:
Wir möchten, dass die Schleife ausgeführt wird, indem das Nullzeichen (das false testet) am Ende der Zeichenfolge angetroffen wird. Dazu muss der Wert vor dem Inkrementieren getestet und auch der Index erhöht werden. Aber nicht unbedingt in dieser Reihenfolge - eine Möglichkeit, dies mit dem Vorinkrement zu codieren, wäre:
Es ist eine Geschmackssache, die klarer ist und wenn die Maschine eine Handvoll Register hat, sollten beide die gleiche Ausführungszeit haben, selbst wenn a [i] eine Funktion ist, die teuer ist oder Nebenwirkungen hat. Ein wesentlicher Unterschied könnte der Exit-Wert des Index sein.
quelle