Undefiniertes Verhalten überarbeitet: Sequenzpunkte und benutzerdefinierte Typen
Die Frage:
In einem früheren Teil über undefiniertes Verhalten und Sequenzpunkte wurde davon ausgegangen, dass der Ausdruck i = i undefiniertes Verhalten für hervorruft eingebaute Typen. Es stellt sich jedoch die Frage: Was ist, wenn der Typ von i benutzerdefiniert ist? Nehmen wir insbesondere an, wir haben einen Klassenindex mit überladenen Operatoren.
Die Antwort: Undefiniertes Verhalten vs. wohldefiniertes Verhalten
Im Gegensatz zur Intuition stellt sich heraus, dass die Ausdruck i = i ruft kein undefiniertes Verhalten für benutzerdefinierte Typen wie Index auf. Dies liegt daran, dass die überladenen Operatoren im Index als Funktionen betrachtet werden. Gemäß dem C-ISO-Standard führt die Funktionsauswertung einen Sequenzpunkt nach der Auswertung der Funktionsargumente und einen weiteren nach dem Kopieren des zurückgegebenen Werts ein.
Sequenzpunkte und überladene Operatoren
Im Fall von i = i wird der Ausdruck i ausgewertet, bevor er als Argument an den Operator = übergeben wird. Dies bedeutet, dass es nach der Auswertung von i einen Sequenzpunkt gibt, der sicherstellt, dass das Objekt i zwischen aufeinanderfolgenden Sequenzpunkten nur einmal geändert wird.
Daher ist der Ausdruck i = i für benutzerdefinierte Typen wie Index äquivalent zum Schreiben von i.operator =(i.operator ());, einem wohldefinierten Ausdruck ohne undefiniertes Verhalten. Das Gleiche gilt für den syntaktisch einfacheren Ausdruck i.add(i.inc());.
Eine subtile Unterscheidung:
Es ist wichtig zu beachten, dass i = i ist kein Ausdruck im Sinne der C-Grammatik. Stattdessen handelt es sich um einen „Anweisungsausdruck“, also eine syntaktische Kombination aus einem Ausdruck und einer Anweisung. Anweisungsausdrücke werden wie normale Anweisungen ausgeführt, ihr Ergebnis kann jedoch auch einer Variablen zugewiesen werden.
Verhalten von a[ i] = i
Wenn a ein Array ist eines integrierten Typs ruft der Ausdruck a[ i] = i undefiniertes Verhalten auf, da der L-Wert a[ i] zweimal ausgewertet wird: einmal im Ausdruck i und noch einmal in der Zuweisung i = i.
Wenn a jedoch ein benutzerdefinierter Typ ist, der den Indexoperator überlädt, kann sich der Ausdruck je nach Implementierung des Indexoperators unterschiedlich verhalten. Wenn der Indexoperator beispielsweise mit const Index& Operator[](Index i) implementiert wird, ist der Ausdruck wohldefiniert, da der L-Wert a[ i] nur einmal ausgewertet wird, bevor der Indexoperator aufgerufen wird.
Die Gültigkeit von i;
Der Ausdruck i; ist in C 03 wohldefiniert, da es äquivalent zu ((i.operator ()).operator ()).operator () ist. Dies liegt daran, dass jeder Operator einen Sequenzpunkt einführt und so sicherstellt, dass das Objekt i zwischen aufeinanderfolgenden Sequenzpunkten nur einmal geändert wird.
Das obige ist der detaillierte Inhalt vonRuft „i = i' undefiniertes Verhalten mit benutzerdefinierten Typen in C auf?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!