000
07.12.2002, 22:29 Uhr
virtual
Sexiest Bit alive (Operator)
|
Was ist der Unterschied zwischen ++i und i++
i++ ("Postfix Inkrement Operator") und ++i ("Präfix Inkrement Operator") machen eigntlich recht Ähnliches: sie erhöhen die Variable i um eins. So schreibt folgende Schleife genauso die zahlen von 1 bis 10 ...
C++: |
for(int i=1; i<=10; [b]i++[/b]) std::cout << i << std::endl;
|
... wie diese hier:
C++: |
for(int i=1; i<=10; [b]++i[/b]) std::cout << i << std::endl;
|
Der Unterschied wird erst deutlich, wenn man die for-Schleife durch eine while-Schleife wie folgt ersetzt:
C++: |
int i=1; while (i<=10) std::cout << [b]i++[/b] << std::endl;
|
gibt auch 1 bis 10 aus, aber:
C++: |
int i=1; while (i<=10) std::cout << [b]++i[/b] << std::endl;
|
gibt die Zahlen 2 bis 11 aus. Wie kommt das?
Jeder Ausdruck in C hat ein wertmäßiges Ergebnis und 0-N Nebeneffekte. Die Ausdrücke "i++" und "++i" haben beide den gleichen Nebeneffekt: sie erhöhen i um 1. Allerdings ist ihr wertmäßiges Ergebnis (also das, was hier ausgegeben wird), unterschiedlich: i++ gibt den Wert von i vor der Erhöhung zurück, ++i gibt den Wert von i nach der Erhöhung zurück.. In vielen Fällen ist man lediglich nur an dem Nebeneffekt interessiert, also daß i um eins erhöht wird, wogegen das wertmäßige Ergebnis nicht von interesse ist. Die beiden for-Schleifen am Anfang sind ein Beispiel dafür: Uns interessiert nur, daß i irgendwie um eins nach oben gezählt wird; aber uns interessiert eigentlich nicht so sehr, wie das wertmäßige Ergebnis ist, dieses berücksichtigen wir nicht. Im Gegensatz dazu wurden bei den while-Schleifen das wertmäßige Ergebnis berücksichtigt, weil es ausgegeben wurde; somit kommen die unterschiedlichen Resultate raus. Das führt uns direkt zur nächsten Frage:
Was ist "besser": ++i oder i++
Wenn das wertmäßige Ergebnis nicht von Interesse ist, wie zB bei der for-Schleife oben, stellt sich die Frage, was denn nun besser ist: ++i oder i++? In den meisten älteren C Sourcen findet man tendenziell mehr i++ als ++i for Schleifen, was zu der Annahme verleiten kann, daß es grundsätzlich besser ist, i++ zu verwenden. Dem ist aber nicht so: In C kann ++i eigentlich nur dann angewendet werden, wenn i ein eingebauter Datentyp wie zB char, int, long, usw. ist. Für diese Typen macht es eigentlich keinen großen Unterschied. In C++ aber macht es einen Unterschied, weil man dort diese Operatoren "überladen", also für eigene Klassen neu definieren kann. Folgende Nn-Sense Klasse soll den Interschied zwischen i++ und ++i verdeutlichen: Wir definieren die Klasse SI, welche ein Integer in String Form sei und definieren die entsprechenden Operatoren. Zunächst schauen wir und die Deklaration an:
C++: |
class SI // StringInteger { std::string str; // ... SI& operator ++ (); // Deklaration prefix inkrement SI operator ++ (int); // Deklaration postfix inkrement };
|
Man erkennt bereits an der Deklaration den Unterschied: Das Präfix-Inkrement gibt eine Referenz zurück (erkennbar am "&" im Rückgabetyp), das Postfix-Inkrement ein temp. Objekt. De Implementierung macht auch deutlich, warum dem so ist. Zuerst das Präfix-Inkrement:
C++: |
// Präfix inkrement bedeutet: erhöhe den Wert des Objektes um eins (Nebeneffekt) // und gebe diesen erhöhten Wert zurück (Wertmäßiges Ergebnis). Also // entspreicht das wertmäßige Ergebnis dem Wert des Objektes nach // Abarbeitung des Operators SI& SI::operator ++ () { // Irgendwie zählen wir den Wert um eins hoch. int n; std::stringstream stream(str); str >> n;
n = n+1;
stream.str(""); stream << n; str = stream.str(); return *this; }
|
Aber der Postfix operator sieht doch was anders aus:
C++: |
// Postfix inkrement bedeutet: erhöhe den Wert des Objektes um eins (Nebeneffekt) // und gebe den Wert von Vor der Erhöhung zurück (Wertmäßiges Ergebnis). // Also entspricht das wertmäßige Ergebnis dem Wert des Objektes vor // abarbeitung des Operators SI SI::operator ++ (int) { SI Kopie(*this) ; // Wir merken uns den alten wert des Objekts. ++(*this); // Wir inkrementieren genau wie beim Präfix Operator ....
return Kopie; // Geben aber die Kopie des alten werts zurück }
|
Mithin muß also von dem Objekt als zusätzliche Aktion ein Konstruktor und ein Destructor Aufruf getätigt werden.
Fazit: Rein von der Performance her ist der Präfixoperator dem Postfixoperator vor zu ziehen (also ++i besser als i++). Jedoch gilt diese Aussage nur, wenn zwei Bedingungen erfüllt sind: 1. Man ist nicht am wertmäßigen Ergebnis des Ausdrucks interessiert 2. Es handelt sich nicht um einen eingebauten Datentypen (denn für diese gibt es hinsichtlich Performance idR keinen Unterschied). -- Gruß, virtual Quote of the Month Ich eß' nur was ein Gesicht hat (Creme 21) Dieser Post wurde am 08.12.2002 um 07:55 Uhr von virtual editiert. |