Zuweisung =

Der Zuweisungs-Operator speichert einen Wert in eine Variable.






5
#include <stdio.h>

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

Details

Der Zuweisungs-Operator erwartet links einen lvalue und rechts einen rvalue und wird von rechts nach links abgearbeitet. Der Rückgabewert ist in C ein rvalue: Der Wert des linken Operanden nach der Zuweisung. in C++ ist der Rückgabewert ein lvalue: Der (mittlerweile zugewiesene) linke Operand selbst.

Handelt es sich bei den Typen der beiden Operanden um Pointer-Typen, so wird nach den Regeln der Pointer-Arithmetik vorgegangen. Handelt es sich bei den Typen der beiden Operanden um arithmetische Typen, so wird gegebenfalls eine automatische arithmetische Umwandlung vorgenommen. Entsprechen die Typen keinen der genannten Typen, so wird ein implizites Casting vorgenommen, welches gegebenfalls zu Compiler-Fehlern oder Warnungen führen kann. Warnungen sowohl von der Pointer-Arithmetik, der arithmetischen Umwandlung, als auch von impliziten Castings können mittels explizitem Casting unterdrückt werden.

Ein häufiger Fehler (insbesondere für Neulinge in der Sprache) ist, das Gleichheitszeichen des Zuweisungsoperators mit dem Gleichheits-Operator == zu verwechseln.



a = 5
  int a = 7;
  if(a == 6){printf("a = 6\n");}
  if(a =  5){printf("a = 5\n");}

Im obigen Beispiel wird nicht, wie möglicherweise erwünscht, der Wert von a mit 5 verglichen, sondern der Wert 5 wird der Variablen a zugewiesen. Durch den Rückgabewert 5 der Variablen ist die Bedingung der if-Struktur erfüllt und die ungewollte Ausgabe wird ausgeführt.

Man beachte, dass der Zuweisungs-Operator in C einen rvalue zurückgibt und keinen lvalue. Folgendes Beispiel ergibt deswegen (nur in C) einen Fehler:


invalid lvalue in unary '&'
  int a;
  &(a = 5);

Überladen des Operators

Der Zuweisungs-Operator hat grundsätzlich die semantische Bedeutung einer Zuweisung eines Wertes zu einer Variablen. Allerdings steht es dem Programmierer frei, eine andere Semantik wie beispielsweise automatische Element-Zugriffe oder Soft-Links mittels dem Zuweisungsoperator zu definieren.

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

inside class
Type operator =(Type);
Type operator =(Type) const;

Man beachte, dass der Zuweisungs-Operator nur innerhalb der Klasse überladen werden kann. Der Autor ist sich momentan nicht klar, was der genaue Grund hierfür ist, zumal alle anderen Zuweisungs-Operatoren eine Überladung ausserhalb der Klasse erlauben. Es ist jedoch zu empfehlen, Zuweisungs-Operatoren grundsätzlich nicht ausserhalb der Klasse zu definieren.

Ausserdem ist zu beachten, dass überladene Zuweisungs-Operatoren angeblich nicht über Klassen vererbt werden. Der Autor konnte diese Aussage jedoch noch nicht evaluieren.

Da der Zuweisungs-Operator in C++ normalerweise einen lvalue zurückgibt, ist der Rückgabetyp der Überladung üblicherweise ein Referenz-Typ (&) der eigenen Klasse, wobei der Rückgabewert normalerweise mit return *this angegeben wird.

Der const-Prototyp macht auf den ersten Moment keinen Sinn, da bei einer Zuweisung 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 präsentiert für einen zweidimensionalen Vektor. Gemäss der Vektoralgebra wird eine Zuweisung eines Skalarwertes zu einem Vektor als die komponentenweise Zuweisung des Wertes zu den Vektorfeldern beschrieben.

















1.000000, 1.000000
#include <cstdio>

class Vector2{
  float a[2];
public:
  void print(){printf("%f, %f\n", a[0], a[1]);}
  
  Vector2& operator =(float s){
    a[0] = s; a[1] = s;
    return *this;
  }
};

int main(){
  Vector2 v;
  v = 1;
  v.print();
  return 0;
}