Namensräume
Varianten
Aktionen

Inkrement-/Dekrement-Operatoren

Von cppreference.com
< cpp‎ | Sprache
 
 
C++ Sprache
Allgemeine Themen
Kontrollfluss
Bedingte Ausführungsaussagen
if
Iterationsanweisungen (Schleifen)
for
Bereichs-for (C++11)
Sprunganweisungen
Funktionen
Funktionsdeklaration
Lambda-Funktionsausdruck
inline-Spezifizierer
Dynamische Ausnahmespezifikationen (bis C++17*)
noexcept-Spezifizierer (C++11)
Ausnahmen
Namensräume
Typen
Spezifizierer
const/volatile
decltype (C++11)
auto (C++11)
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Speicherdauer-Spezifizierer
Initialisierung
Ausdrücke
Alternative Darstellungen
Literale
Boolesch - Ganzzahl - Gleitkommazahl
Zeichen - String - nullptr (C++11)
Benutzerdefinierte (C++11)
Dienstprogramme
Attribute (C++11)
Typen
typedef-Deklaration
Typalias-Deklaration (C++11)
Umwandlungen
Speicherzuweisung
Klassen
Klassenspezifische Funktionseigenschaften
explicit (C++11)
static

Spezielle Member-Funktionen
Templates
Sonstiges
 
 

Inkrement-/Dekrement-Operatoren erhöhen oder verringern den Wert des Objekts.

Operatorname Syntax Über​lad​bar Prototypenbeispiele (für class T)
Innerhalb der Klassendefinition Außerhalb der Klassendefinition
Präfix-Inkrement ++a Ja T& T::operator++(); T& operator++(T& a);
Präfix-Dekrement --a Ja T& T::operator--(); T& operator--(T& a);
Suffix-Inkrement a++ Ja T T::operator++(int); T operator++(T& a, int);
Suffix-Dekrement a-- Ja T T::operator--(int); T operator--(T& a, int);
Anmerkungen
  • Präfix-Versionen der eingebauten Operatoren geben *Referenzen* zurück, und Suffix-Versionen geben *Werte* zurück. Typische benutzerdefinierte Überladungen folgen diesem Muster, damit die benutzerdefinierten Operatoren auf die gleiche Weise verwendet werden können wie die eingebauten. Bei einer benutzerdefinierten Operatorüberladung kann jedoch jeder Typ als Rückgabetyp verwendet werden (einschließlich void).
  • Der int-Parameter ist ein Dummy-Parameter, der verwendet wird, um zwischen Präfix- und Suffix-Versionen der Operatoren zu unterscheiden. Wenn der benutzerdefinierte Suffix-Operator aufgerufen wird, ist der Wert, der in diesem Parameter übergeben wird, immer Null, obwohl er durch Aufruf des Operators über die Funktionsaufrufnnotation (z. B. a.operator++(2) oder operator++(a, 2)) geändert werden kann.

Inhalt

[edit] Präfix-Operatoren

Die Präfix-Inkrement- und Dekrement-Ausdrücke haben die Form

++ expression
-- expression
1) Präfix-Inkrement (Präfix-Inkrement)
2) Präfix-Dekrement (Präfix-Dekrement)

[edit] Eingebaute Präfix-Operatoren

1) Der Ausdruck ++x ist äquivalent zu x += 1, mit den folgenden Ausnahmen:
  • Wenn der Typ von expression (möglicherweise mit volatile qualifiziert) bool ist, wird expression auf true gesetzt. Ein solches Inkrement ist veraltet.
(bis C++17)
  • Wenn der Typ von expression (möglicherweise cv-qualifiziert) bool ist, ist das Programm schlecht geformt.
(seit C++17)
  • Wenn der Typ von expression mit volatile qualifiziert ist, ist das Inkrement veraltet.
(seit C++20)
2) Der Ausdruck --x ist äquivalent zu x -= 1, mit den folgenden Ausnahmen:
  • Wenn der Typ von expression (möglicherweise cv-qualifiziert) bool ist, ist das Programm schlecht geformt.
  • Wenn der Typ von expression mit volatile qualifiziert ist, ist das Dekrement veraltet.
(seit C++20)

[edit] Überladungen

Bei der Überladungsauflösung für benutzerdefinierte Operatoren nehmen für jeden optional mit volatile qualifizierten arithmetischen Typ `A`, der kein bool ist, und für jeden optional mit volatile qualifizierten Zeiger `P` auf einen optional cv-qualifizierten Objekttyp die folgenden Funktionssignaturen an der Überladungsauflösung teil:

A& operator++(A&)
bool& operator++(bool&)
(veraltet)(bis C++17)
P& operator++(P&)
A& operator--(A&)
P& operator--(P&)

[edit] Suffix-Operatoren

Die Suffix-Inkrement- und Dekrement-Ausdrücke haben die Form

expression ++
expression --
1) Suffix-Inkrement (Suffix-Inkrement)
2) Suffix-Dekrement (Suffix-Dekrement)

[edit] Eingebaute Suffix-Operatoren

Das Ergebnis von Suffix-Inkrement oder -Dekrement ist der Wert, der durch Anwenden der Lvalue-zu-Rvalue-Konvertierung auf expression (vor der Modifikation) erhalten wird. Der Typ des Ergebnisses ist die cv-unqualifizierte Version des Typs von expression.

Wenn expression kein modifizierbarer Lvalue eines arithmetischen Typs ist außer (möglicherweise cv-qualifiziert) bool(seit C++17), oder ein Zeiger auf einen vollständigen Objekttyp, ist das Programm schlecht geformt.

Wenn der Typ von expression mit volatile qualifiziert ist, sind Inkrement oder Dekrement veraltet.

(seit C++20)
1) Der Wert von expression wird modifiziert, als ob er der Operand des Präfix-Operators ++ wäre.
2) Der Wert von expression wird modifiziert, als ob er der Operand des Präfix-Operators -- wäre.

Die Wertberechnung eines Suffix-Inkrements oder -Dekrements erfolgt *vor* der Modifikation von expression. In Bezug auf einen beliebig sequenzierten Funktionsaufruf ist die Operation eines Suffix-Inkrements oder -Dekrements eine einzelne Auswertung.

[edit] Überladungen

Bei der Überladungsauflösung für benutzerdefinierte Operatoren nehmen für jeden optional mit volatile qualifizierten arithmetischen Typ `A`, der kein bool ist, und für jeden optional mit volatile qualifizierten Zeiger `P` auf einen optional cv-qualifizierten Objekttyp die folgenden Funktionssignaturen an der Überladungsauflösung teil:

A operator++(A&, int)
bool operator++(bool&, int)
(veraltet)(bis C++17)
P operator++(P&, int)
A operator--(A&, int)
P operator--(P&, int)

[edit] Beispiel

#include <iostream>
 
int main()
{
    int n1 = 1;
    int n2 = ++n1;
    int n3 = ++ ++n1;
    int n4 = n1++;
//  int n5 = n1++ ++;   // error
//  int n6 = n1 + ++n1; // undefined behavior
    std::cout << "n1 = " << n1 << '\n'
              << "n2 = " << n2 << '\n'
              << "n3 = " << n3 << '\n'
              << "n4 = " << n4 << '\n';
}

Ausgabe

n1 = 5
n2 = 2
n3 = 4
n4 = 4

[edit] Hinweise

Aufgrund der beteiligten Nebeneffekte müssen eingebaute Inkrement- und Dekrement-Operatoren mit Vorsicht verwendet werden, um undefiniertes Verhalten durch Verletzung von Sequenzierungsregeln zu vermeiden.

Da bei Suffix-Inkrement und -Dekrement eine temporäre Kopie des Objekts erstellt wird, sind Präfix-Inkrement- oder -Dekrement-Operatoren in Kontexten, in denen der zurückgegebene Wert nicht verwendet wird, in der Regel effizienter.

[edit] Standardbibliothek

Inkrement- und Dekrement-Operatoren sind für viele Standardbibliothekstypen überladen. Insbesondere überlädt jeder LegacyIterator operator++ und jeder LegacyBidirectionalIterator operator--, auch wenn diese Operatoren für den jeweiligen Iterator keine Operationen sind.

Überladungen für arithmetische Typen
inkrementiert oder dekrementiert den atomaren Wert um eins
(öffentliche Memberfunktion von std::atomic<T>) [edit]
inkrementiert oder dekrementiert die Tick-Anzahl
(öffentliche Memberfunktion von std::chrono::duration<Rep,Period>) [edit]
Überladungen für Iteratortypen
bewegt den Iterator vorwärts
(öffentliche Memberfunktion von std::raw_storage_iterator<OutputIt,T>) [edit]
bewegt den reverse_iterator vorwärts oder rückwärts
(öffentliche Memberfunktion von std::reverse_iterator<Iter>) [edit]
bewegt den move_iterator vorwärts oder rückwärts
(öffentliche Memberfunktion von std::move_iterator<Iter>) [edit]
no-op
(öffentliche Memberfunktion von std::front_insert_iterator<Container>) [edit]
no-op
(öffentliche Memberfunktion von std::back_insert_iterator<Container>) [edit]
no-op
(öffentliche Memberfunktion von std::insert_iterator<Container>) [edit]
bewegt den Iterator vorwärts
(öffentliche Memberfunktion von std::istream_iterator<T,CharT,Traits,Distance>) [edit]
no-op
(öffentliche Memberfunktion von std::ostream_iterator<T,CharT,Traits>) [edit]
bewegt den Iterator vorwärts
(öffentliche Memberfunktion von std::istreambuf_iterator<CharT,Traits>) [edit]
no-op
(öffentliche Memberfunktion von std::ostreambuf_iterator<CharT,Traits>) [edit]
bewegt den Iterator zum nächsten Treffer
(öffentliche Memberfunktion von std::regex_iterator<BidirIt,CharT,Traits>) [edit]
bewegt den Iterator zum nächsten Teilübereinstimmung
(öffentliche Memberfunktion von std::regex_token_iterator<BidirIt,CharT,Traits>) [edit]

[edit] Fehlerberichte

Die folgenden Verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C++-Standards angewendet.

DR angewendet auf Verhalten wie veröffentlicht Korrigiertes Verhalten
CWG 2855 C++98 Die üblichen arithmetischen Konvertierungen werden für eingebaute Präfix-Inkrementierung und
Präfix-Dekrementierung angewendet, wurden aber nicht für ihre Suffix-Gegenstücke angewendet[1]
auch angewendet
CWG 2901 C++98 Lvalue-zu-Rvalue-Konvertierungen wurden nicht angewendet
für eingebaute Suffix-Inkrementierung und Suffix-Dekrementierung
angewendet
  1. Der Präfix-Operator ++x ist äquivalent zu x += 1, und letzteres ist für übliche arithmetische Konvertierungen anwendbar (d. h. es ergibt einen gemeinsamen Typ zwischen decltype(x) und int). Der Effekt des Suffix-Operators x++ ist jedoch einfach das "Hinzufügen von eins zu x", es gibt keinen binären Operator, sodass keine üblichen arithmetischen Konvertierungen stattfinden.

[edit] Siehe auch

Operatorrangfolge

Operatorüberladung

Häufige Operatoren
Zuweisung Inkrement
Dekrement
Arithmetik Logisch Vergleich Member
Zugriff
Sonstiges

a = b
a += b
a -= b
a *= b
a /= b
a %= b
a &= b
a |= b
a ^= b
a <<= b
a >>= b

++a
--a
a++
a--

+a
-a
a + b
a - b
a * b
a / b
a % b
~a
a & b
a | b
a ^ b
a << b
a >> b

!a
a && b
a || b

a == b
a != b
a < b
a > b
a <= b
a >= b
a <=> b

a[...]
*a
&a
a->b
a.b
a->*b
a.*b

Funktionsaufruf

a(...)
Komma

a, b
Ternär

a ? b : c
Spezielle Operatoren

static_cast konvertiert einen Typ in einen anderen verwandten Typ
dynamic_cast konvertiert innerhalb von Vererbungshierarchien
const_cast fügt cv-Qualifizierer hinzu oder entfernt sie
reinterpret_cast konvertiert einen Typ in einen nicht verwandten Typ
C-Stil Cast konvertiert einen Typ in einen anderen durch eine Mischung aus static_cast, const_cast und reinterpret_cast
new erstellt Objekte mit dynamischer Speicherverwaltung
delete zerstört zuvor mit new-Ausdruck erstellte Objekte und gibt den zugewiesenen Speicherbereich frei
sizeof fragt die Größe eines Typs ab
sizeof... fragt die Größe eines packs ab (seit C++11)
typeid fragt die Typinformationen eines Typs ab
noexcept prüft, ob ein Ausdruck eine Ausnahme auslösen kann (seit C++11)
alignof fragt die Ausrichtungsvoraussetzungen eines Typs ab (seit C++11)

C-Dokumentation für Inkrement-/Dekrement-Operatoren