Zuweisungsoperatoren
Zuweisungsoperatoren modifizieren den Wert des Objekts.
| Operatorname | Syntax | Überladbar | Prototypenbeispiele (für class T) | |
|---|---|---|---|---|
| Innerhalb der Klassendefinition | Außerhalb der Klassendefinition | |||
| einfache Zuweisung | a = b
|
Ja | T& T::operator =(const T2& b); | N/A |
| Addition-Zuweisung | a += b
|
Ja | T& T::operator +=(const T2& b); | T& operator +=(T& a, const T2& b); |
| Subtraktions-Zuweisung | a -= b
|
Ja | T& T::operator -=(const T2& b); | T& operator -=(T& a, const T2& b); |
| Multiplikations-Zuweisung | a *= b
|
Ja | T& T::operator *=(const T2& b); | T& operator *=(T& a, const T2& b); |
| Divisions-Zuweisung | a /= b
|
Ja | T& T::operator /=(const T2& b); | T& operator /=(T& a, const T2& b); |
| Rest-Zuweisung | a %= b
|
Ja | T& T::operator %=(const T2& b); | T& operator %=(T& a, const T2& b); |
| Bitweises AND-Zuweisung | a &= b
|
Ja | T& T::operator &=(const T2& b); | T& operator &=(T& a, const T2& b); |
| Bitweises OR-Zuweisung | a |= b
|
Ja | T& T::operator |=(const T2& b); | T& operator |=(T& a, const T2& b); |
| Bitweises XOR-Zuweisung | a ^= b
|
Ja | T& T::operator ^=(const T2& b); | T& operator ^=(T& a, const T2& b); |
| Bitweises Links-Shift-Zuweisung | a <<= b
|
Ja | T& T::operator <<=(const T2& b); | T& operator <<=(T& a, const T2& b); |
| Bitweises Rechts-Shift-Zuweisung | a >>= b
|
Ja | T& T::operator >>=(const T2& b); | T& operator >>=(T& a, const T2& b); |
| ||||
Inhalt |
[bearbeiten] Definitionen
Kopierzuweisung ersetzt den Inhalt des Objekts a durch eine Kopie des Inhalts von b (b wird nicht verändert). Für Klassentypen wird dies in einer speziellen Mitgliedsfunktion durchgeführt, die im Kopierzuweisungsoperator beschrieben ist.
|
Verschiebungszuweisung ersetzt den Inhalt des Objekts a durch den Inhalt von b und vermeidet nach Möglichkeit das Kopieren (b kann modifiziert werden). Für Klassentypen wird dies in einer speziellen Mitgliedsfunktion durchgeführt, die im Verschiebungszuweisungsoperator beschrieben ist. |
(seit C++11) |
Für Nicht-Klassentypen sind Kopier- und Verschiebungszuweisung nicht unterscheidbar und werden als direkte Zuweisung bezeichnet.
Zusammengesetzte Zuweisung ersetzt den Inhalt des Objekts a durch das Ergebnis einer binären Operation zwischen dem vorherigen Wert von a und dem Wert von b.
[bearbeiten] Syntax von Zuweisungsoperatoren
Die Zuweisungsausdrücke haben die Form
target-expr = new-value |
(1) | ||||||||
| target-expr op new-value | (2) | ||||||||
| target-expr | - | der Ausdruck[1], dem zugewiesen wird |
| op | - | einer von *=, /= %=, += -=, <<=, >>=, &=, ^=, |= |
| new-value | - | der Ausdruck[2](bis C++11)Initialisierungsklausel(seit C++11) zum Zuweisen an das Ziel |
- ↑ target-expr muss eine höhere Priorität als ein Zuweisungsausdruck haben.
- ↑ new-value darf kein Komma-Ausdruck sein, da seine Priorität niedriger ist.
|
Wenn new-value kein Ausdruck ist, passt der Zuweisungsausdruck niemals zu einem überladenen zusammengesetzten Zuweisungsoperator. |
(seit C++11) |
[bearbeiten] Eingebauter einfacher Zuweisungsoperator
Für die eingebaute einfache Zuweisung muss target-expr ein modifizierbarer lvalue sein.
Das Objekt, auf das target-expr verweist, wird modifiziert, indem sein Wert durch das Ergebnis von new-value ersetzt wird. Wenn das referenzierte Objekt vom ganzzahligen Typ T ist und das Ergebnis von new-value vom entsprechenden vorzeichenbehafteten/vorzeichenlosen ganzzahligen Typ ist, wird der Wert des Objekts durch den Wert vom Typ T mit der gleichen Wertdarstellung wie das Ergebnis von new-value ersetzt.
Das Ergebnis einer eingebauten einfachen Zuweisung ist ein lvalue vom Typ von target-expr, der auf target-expr verweist. Wenn target-expr ein Bitfeld ist, ist das Ergebnis ebenfalls ein Bitfeld.
[bearbeiten] Zuweisung aus einem Ausdruck
Wenn new-value ein Ausdruck ist, wird er in den cv-unqualifizierten Typ von target-expr implizit konvertiert. Wenn target-expr ein Bitfeld ist, das den Wert des Ausdrucks nicht darstellen kann, ist der resultierende Wert des Bitfelds implementierungsabhängig.
Wenn target-expr und new-value überlappende Objekte bezeichnen, ist das Verhalten undefiniert (es sei denn, die Überlappung ist exakt und der Typ ist derselbe).
|
Wenn der Typ von target-expr mit volatile qualifiziert ist, wird die Zuweisung als veraltet (deprecated) eingestuft, es sei denn, der (möglicherweise in Klammern gesetzte) Zuweisungsausdruck ist ein Ausdruck mit verworfenem Wert oder ein potenziell ausgewerteter Operand. |
(seit C++20) |
Zuweisung aus einer Initialisierungsklausel, die kein Ausdruck istnew-value darf nur in den folgenden Situationen kein Ausdruck sein
#include <complex> std::complex<double> z; z = {1, 2}; // meaning z.operator=({1, 2}) z += {1, 2}; // meaning z.operator+=({1, 2}) int a, b; a = b = {1}; // meaning a = b = 1; a = {1} = b; // syntax error |
(seit C++11) |
Bei der Überladungsauflösung für benutzerdefinierte Operatoren nehmen für jeden Typ T die folgenden Funktionssignaturen an der Überladungsauflösung teil
| T*& operator=(T*&, T*); |
||
| T*volatile & operator=(T*volatile &, T*); |
||
Für jeden Aufzählungs- oder Zeigertyp auf ein Mitglied T, optional mit volatile qualifiziert, nimmt die folgende Funktionssignatur an der Überladungsauflösung teil
| T& operator=(T&, T); |
||
Für jedes Paar A1 und A2, wobei A1 ein arithmetischer Typ (optional mit volatile qualifiziert) und A2 ein geförderter arithmetischer Typ ist, nimmt die folgende Funktionssignatur an der Überladungsauflösung teil
| A1& operator=(A1&, A2); |
||
[bearbeiten] Eingebauter zusammengesetzter Zuweisungsoperator
Das Verhalten jedes eingebauten zusammengesetzten Zuweisungsausdrucks target-expr op = new-value ist exakt dasselbe wie das Verhalten des Ausdrucks target-expr = target-expr op new-value, mit der Ausnahme, dass target-expr nur einmal ausgewertet wird.
Die Anforderungen an target-expr und new-value von eingebauten einfachen Zuweisungsoperatoren gelten ebenfalls. Darüber hinaus
- Für += und -= muss der Typ von target-expr ein arithmetischer Typ oder ein Zeiger auf einen (optional cv-qualifizierten) vollständig definierten Objekttyp sein.
- Für alle anderen zusammengesetzten Zuweisungsoperatoren muss der Typ von target-expr ein arithmetischer Typ sein.
Bei der Überladungsauflösung für benutzerdefinierte Operatoren nehmen für jedes Paar A1 und A2, wobei A1 ein arithmetischer Typ (optional mit volatile qualifiziert) und A2 ein geförderter arithmetischer Typ ist, die folgenden Funktionssignaturen an der Überladungsauflösung teil
| A1& operator*=(A1&, A2); |
||
| A1& operator/=(A1&, A2); |
||
| A1& operator+=(A1&, A2); |
||
| A1& operator-=(A1&, A2); |
||
Für jedes Paar I1 und I2, wobei I1 ein ganzzahliger Typ (optional mit volatile qualifiziert) und I2 ein geförderter ganzzahliger Typ ist, nehmen die folgenden Funktionssignaturen an der Überladungsauflösung teil
| I1& operator%=(I1&, I2); |
||
| I1& operator<<=(I1&, I2); |
||
| I1& operator>>=(I1&, I2); |
||
| I1& operator&=(I1&, I2); |
||
| I1& operator^=(I1&, I2); |
||
| I1& operator|=(I1&, I2); |
||
Für jeden optional cv-qualifizierten Objekttyp T nehmen die folgenden Funktionssignaturen an der Überladungsauflösung teil
| T*& operator+=(T*&, std::ptrdiff_t); |
||
| T*& operator-=(T*&, std::ptrdiff_t); |
||
| T*volatile & operator+=(T*volatile &, std::ptrdiff_t); |
||
| T*volatile & operator-=(T*volatile &, std::ptrdiff_t); |
||
[bearbeiten] Beispiel
#include <iostream> int main() { int n = 0; // not an assignment n = 1; // direct assignment std::cout << n << ' '; n = {}; // zero-initialization, then assignment std::cout << n << ' '; n = 'a'; // integral promotion, then assignment std::cout << n << ' '; n = {'b'}; // explicit cast, then assignment std::cout << n << ' '; n = 1.0; // floating-point conversion, then assignment std::cout << n << ' '; // n = {1.0}; // compiler error (narrowing conversion) int& r = n; // not an assignment r = 2; // assignment through reference std::cout << n << ' '; int* p; p = &n; // direct assignment p = nullptr; // null-pointer conversion, then assignment std::cout << p << ' '; struct { int a; std::string s; } obj; obj = {1, "abc"}; // assignment from a braced-init-list std::cout << obj.a << ':' << obj.s << '\n'; }
Mögliche Ausgabe
1 0 97 98 1 2 (nil) 1:abc
[bearbeiten] Berichte über Fehler
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 1527 | C++11 | Bei Zuweisungen an Objekte vom Klassentyp konnte der rechte Operand eine Initialisierungsliste sein, nur wenn die Zuweisung durch einen benutzerdefinierten Zuweisungsoperator definiert war |
entfernte benutzerdefinierte Zuweisungsbeschränkung |
| CWG 1538 | C++11 | E1 = {E2} war äquivalent zu E1 = T(E2) ( T ist der Typ von E1), dies führte zu einem C-Style-Cast |
es ist äquivalent zu E1 = T{E2} |
| CWG 2654 | C++20 | zusammengesetzte Zuweisungsoperatoren für volatile -qualifizierte Typen waren inkonsistent als veraltet eingestuft |
keiner von ihnen ist veraltet |
| CWG 2768 | C++11 | eine Zuweisung von einer Initialisierungsklausel, die kein Ausdruck ist, an einen Skalarwert würde eine direkte Listeninitialisierung durchführen |
führt eine Kopierlisten- Initialisierung stattdessen durch |
| CWG 2901 | C++98 | der Wert, der einem unsigned int Objekt über ein int lvalue zugewiesen wird, ist unklar |
wurde klargestellt |
| P2327R1 | C++20 | bitweise zusammengesetzte Zuweisungsoperatoren für volatile Typen wurden als veraltet eingestuft, obwohl sie für einige Plattformen nützlich waren |
sie sind es nicht deprecated |
[bearbeiten] Siehe auch
| Häufige Operatoren | ||||||
|---|---|---|---|---|---|---|
| Zuweisung | Inkrement Dekrement |
Arithmetik | Logisch | Vergleich | Member Zugriff |
Sonstiges |
|
a = b |
++a |
+a |
!a |
a == b |
a[...] |
Funktionsaufruf a(...) |
| Komma a, b | ||||||
| Ternär a ? b : c | ||||||
| Spezielle Operatoren | ||||||
|
static_cast konvertiert einen Typ in einen anderen verwandten Typ | ||||||
| C-Dokumentation für Zuweisungsoperatoren
|