C
DeepCopy schrieb:
camper schrieb:
zudem befinden sich dazwischen keine sequence points.
Was genau meinst du damit ?
genau das. Befindet sich ein Sequenzpunkt zwischen zwei Ausdrücken a und b, so ist garantiert, dass jede Änderung von Objekten, die durch die Auswertung von a bedingt sind, abgeschlossen wurden, bevor die Auswertung von b stattfindet (jedenfalls insoweit die Auswertung von b auf diese Objekte zugreift).
Betrachte
void f(int,int);
int inc(int& x) { return ++x; }
int a = 0; ++a, ++a; // (1) Ergebnis: a == 2
int v = 0; ++b + ++b; // (2) UB
int c = 0; f( ++c, ++c ); // (3) UB
int d = 0; f( inc(d), d ); // (4) unspezifiziert: entweder f(1,1) oder f(1,0)
Der Kommaoperator stellt einen Sequenzpunkt zischen den beiden Operanden dar, mithin hat a sicher den Wert 1, bevor die Auswertung der rechten Seite beginnt.
Im 2. Fall besteht keine solche Garantie - wird nun ein Objekt mehrfach verändert wie in Fall 2 und befindet sich dazwischen kein Sequenzpunkt, resultiert daraus undefiniertes Verhalten.
Gleiches gilt für Fall 3.
Fall 4 wiederum ist nur unspezifiert, denn am Beginn und Ende jedes Funktionsaufrufes (also nach erfolgter Initialisierung aller Funktionsparameter, sowie beim Verlassen nach Initialiserung des Funktionsergebnisses und der Zerstörung lokaler Variablen) befindet sich jeweils ein Sequenzpunkt.
Die Unbestimmtheit der Auswertung betrifft auch Teilausdrücke:
class X;
void sink(auto_ptr<X> a,auto_ptr<X> b);
sink(auto_ptr<X>(new X(...)),auto_ptr<X>(new X(...));
Trotz der Verwendung von auto_ptr haben wir es hier mit einem potentiellen Leck zu tun:
nachdem das erste X-Objekt erfolgreich angefordert und initialisiert wurde, ist nicht garantiert, dass der resultierende rohe Zeiger sogleich zur Initialiserung des auto_ptr benutzt wird, es könnte stattdessen erst das zweite new ausgeführt werden. Schlägt dieses 2. new nun fehl (exception), wird das zuerst angeforderte Objekt nicht wieder vernichtet werden.