Namensräume
Varianten
Aktionen

Zuweisungsoperatoren

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
 
 

Zuweisungsoperatoren modifizieren den Wert des Objekts.

Operatorname  Syntax  Über​lad​bar 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);
Anmerkungen
  • Alle eingebauten Zuweisungsoperatoren geben *this zurück, und die meisten benutzerdefinierten Überladungen geben ebenfalls *this zurück, sodass die benutzerdefinierten Operatoren auf die gleiche Weise wie die eingebauten verwendet werden können. Bei einer benutzerdefinierten Operatorüberladung kann jedoch jeder Typ als Rückgabetyp verwendet werden (einschließlich void).
  • T2 kann jeder Typ sein, einschließlich T.

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
  1. target-expr muss eine höhere Priorität als ein Zuweisungsausdruck haben.
  2. new-value darf kein Komma-Ausdruck sein, da seine Priorität niedriger ist.
1) Einfacher Zuweisungsausdruck.
2) Zusammengesetzter Zuweisungsausdruck.

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 ist

new-value darf nur in den folgenden Situationen kein Ausdruck sein

  • target-expr ist von einem Skalar-Typ T, und new-value ist leer oder hat nur ein Element. In diesem Fall, gegeben eine erfundene Variable t, deklariert und initialisiert als T t = new-value , ist die Bedeutung von x = new-value  x = t.
  • target-expr ist von einem Klassentyp. In diesem Fall wird new-value als Argument an die durch Überladungsauflösung ausgewählte Zuweisungsoperatorfunktion übergeben.
#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

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 Zuweisungsoperatoren