Post-Inkrement ++

Der Post-Inkrement-Operator erhöht den angegebenen Operanden um eine Einheit und speichert den Wert zurück in den Operanden. Für arithmetische Typen entspricht dies der Addition mit 1. Im Gegensatz zum Pre-Increment-Operator steht der Operator ++ NACH dem Operanden und wird ausgeführt, NACHDEM der Operand zurückgegeben wurde.





5

6
#include <stdio.h>

int main(){
  int a = 5;
  printf("%d\n",  a);
  a++;
  printf("%d\n",  a);
  return 0;
}

Siehe auch Pre-Increment-Operator ++, Post-Decrement-Operator --, Pre-Decrement-Operator --

Details

Der Post-Inkrement-Operator erwartet einen Operanden als lvalue und wird von links nach rechts abgearbeitet. Der Rückgabewert ist ein rvalue: Der Wert des (vorerst unveränderten) Operanden, der angegeben wurde.

Zwar ist der Post-Inkrement-Operator für sämtliche arithmetische Typen zulässig, jedoch trifft man ihn hauptsächlich bei Integer-Typen und bei Pointern an. Wenn der Post-Inkrement-Operator auf einen Pointer angewendet wird, so wird der Pointer um eine Typ-Grösse erhöht.



1

2
int a[5] = {1, 2, 3, 4, 5};
int* b = a;
printf("%d\n",  *b);
b++;
printf("%d\n",  *b);

Wenn der Operand als konstant deklariert ist, so gibt der Compiler einen Fehler wie etwa increment of read-only variable, aus. Anmerkung: Ein (nicht als konstant deklarierter) Pointer, der auf einen konstanten Wert zeigt, kann selbstverständlich inkrementiert werden.

Durch die Addition einer Einheit kann es bei arithmetischen Typen vorkommen, dass ein Overflow passiert, was bei Integer-Typen zu einem Wrap-Around führt



0
unsigned char a = 255;
a++;
printf("%d\n",  a);

Der Post-Increment-Operator ist ein Operator mit Nebeneffekt, was bedeutet, dass der angegebene Operand sowohl gelesen, als auch geschrieben wird. Der Unterschied des Post-Inkrement-Operators zum Pre-Increment-Operator ist, dass der inkrementierte Wert in den Operanden zurückgeschrieben wird, NACHDEM der Operand als Rückgabewert verwendet wurde, wohingegen der Pre-Inkrement-Operator den Operanden zuerst erhöht und ihn danach als Rückgabewert auffasst. Folgendes Beispiel verdeutlicht diesen Unterschied:


10
11
12
int a = 10;
printf("%d\n",  a++);
printf("%d\n",  a);
printf("%d\n",  ++a);

Überladen des Operators

Der Post-Increment-Operator hat grundsätzlich die semantische Bedeutung einer Addition einer Einheit im mathematischem Sinne, jedoch sind auch andere, ähnliche semantische Bedeutungen möglich. Es hat sich zudem eingebürgert, den Increment-Operator als Navigations-Operator zu benutzen, wie er bei Iteratoren benötigt wird. Grundsätzlich ist der Post-Increment-Operator zu verstehen als ein Operator, der den Operanden selbst verändert, allerdings erlaubt die Operatoren-Überladung auch jegliche andere Implementation.

Um bei den Inkrement-Operatoren zwischen der Pre- und der Post-Variante zu unterscheiden, wird bei der Post-Variante ein zusätzlicher int-Parameter deklariert. Das Ausprogrammieren der Post-Variante erweist sich zudem normalerweise als schwieriger als die Pre-Variante, da ein Objekt mit dem Inhalt VOR Anwendung des Operators zurückgegeben werden soll. Dies ist nebenbei bemerkt der Grund, wieso der Autor anstelle von ManderC++ den Titel Mander++C gewählt hat. Genauere Details über das Überladen der Pre-Variante ist beim Pre-Increment-Operator nachzulesen.

Die Prototypen für das Überladen des Post-Increment-Operators sind die folgenden (Einschränkungen und Erläuterungen siehe Überladen von Operatoren):

inside class


outside class
Type operator ++(int);
Type operator ++(int) const;

Type operator ++(Type, int);

Da der Post-Increment-Operator normalerweise den Operanden zurückgibt, bevor er verändert wird, ist der Rückgabetyp der Post-Variante häufig ein Value-Typ der eigenen Klasse. Man beachte hierfür auch den Unterschied zum Pre-Increment-Operator.

Der const-Prototyp macht auf den ersten Moment keinen Sinn, da bei einem Post-Increment-Operator im herkömmlichen Sinne das betroffene Objekt immer verändert wird. Man beachte jedoch, dass diese semantische Bedeutung nicht zwingend eingehalten werden muss und ausserdem Felder von Klassen mittels der mutable-Speicherklasse deklariert werden können. Bei Auftreten beider Prototyp-Varianten in einer Klasse wird jedoch grundsätzlich (ohne die Notwendigkeit eines const-Aufrufes) die nicht-const-Überladung aufgerufen.

Im folgenden Beispiel wird eine Klasse für einen dreidimensionalen Punkt verwendet. Der überladene Post-Inkrement-Operator erhöht alle Einträge des Punktes um den Wert 1.





















1.000000, 2.000000, 3.000000
1.000000, 2.000000, 3.000000
2.000000, 3.000000, 4.000000
#include <cstdio>

class Point{
  float x, y, z;
public:
  Point(float a, float b, float c){
    x = a; y = b; z = c;
  }
  Point operator ++(int value){
    float ox = x;
    float oy = y;
    float oz = z;
    x++; y++; z++;
    return Point(ox, oy, oz);
  }
  void print(){printf("%f, %f, %f\n", x, y, z);}
};

int main(){
  Point p(1, 2, 3);
  p.print();
  p++.print();
  p.print();
  return 0;
}

Man beachte, dass der zusätzliche int-Parameter als dummy-Variable gilt: Der Inhalt der Variablen wird bei normalem Gebrauch des Operators vom Compiler auf 0 gesetzt. Er kann jedoch mittels eines expliziten operator-Funktionsaufrufes willkürlich gesetzt werden, sodass dieser Variable vom Programmierer eine semantische Bedeutung zugeordnet werden kann. Dies ist jedoch nicht üblich und nicht zu empfehlen, ausserdem ist der explizite Aufruf mittels der operator-Schreibweise die einzige Möglichkeit, dieses Argument programmiertechnisch zu nutzen.













12345

0

42
#include <cstdio>

class Test{
  int dummy;
public:
  Test(){dummy = 12345;}
  void operator ++(int value){dummy = value;}
  void print(){printf("%d\n", dummy);}
};

int main(){
  Test t;
  t.print();
  t++;
  t.print();
  t.operator ++(42);
  t.print();
  return 0;
}