In C ++ 11 und später tritt UB auf, wenn zwei Schreibvorgänge oder ein Schreib- und ein Lesevorgang, die nicht sequenziert sind, auf denselben Speicherort zugreifen. Aber ++x
entspricht x+=1
, also ++ ++n1
entspricht (n1+=1)+=1
, und hier erfolgen die Lese- und Schreibvorgänge aufgrund der Eigenschaften von Zuweisungs- und zusammengesetzten Zuweisungsoperatoren in einer strengen Reihenfolge: zuerst wird n1
gelesen , dann wird eins plus der ursprüngliche Wert geschrieben, dann wird der resultierende Wert erneut gelesen, dann wird ein plus dieser Wert zurückgeschrieben.
In C ++ 03 war dies UB, wegen der alten Regel, auf die Sie verweisen: Zwischen den beiden Modifikationen gibt es keinen Sequenzpunkt. Aber in C ++ 11 gibt es keine Sequenzpunkte mehr; stattdessen gibt es die "sequenzielle vor" Teilaufordnung.
Siehe Brians Antwort für einfachere Begriffe.
Es ist legal, weil der C ++ Standard es so sagt, die Betonung liegt bei mir ... Geht nach dem C ++ 14 Entwurf
5.3.2 Inkrementieren und Dekrementieren [expr.pre.incr]
Der Operand von Präfix ++ wird durch Hinzufügen von 1 geändert oder auf "true" gesetzt ist bool (diese Verwendung ist veraltet). Der Operand soll veränderbar sein Wert. Der Typ des Operanden muss ein arithmetischer Typ oder a sein Zeiger auf einen vollständig definierten Objekttyp. Das Ergebnis ist die Aktualisierter Operand; Es ist ein Lvalue , und es ist ein Bit-Feld, wenn das Operand ist ein Bitfeld. Wenn x nicht vom Typ bool ist, ist der Ausdruck ++ x entspricht x + = 1
Also, das ist absolut legal
%Vor%Ausgabe
%Vor%1.9 Programmausführung [intro.execution]
15 ... Wenn eine Nebenwirkung auf ein Skalarobjekt relativ zu beiden nicht sequenziert ist ein weiterer Nebeneffekt auf das self scalar object oder eine Wertberechnung Mit dem Wert des gleichen skalaren Objekts ist das Verhalten nicht definiert. ...
Und es ist ein Beispiel:
%Vor%Tags und Links c++ prefix-operator