Zuweisungen in C++ (Zuweisungen in C++), Lektion, Seite 723307
https://www.purl.org/stefan_ram/pub/zuweisungen_c++ (Permalink) ist die kanonische URI dieser Seite.
Stefan Ram
C++-Kurs

Zuweisungen in C++ 

Zuweisung

Bei der Initialisierung wird ein neues Objekt mit einem bestimmten Wert angelegt. Die Initialisierung kann beispielsweise bei der Ausführung einer Variablendefinition erfolgen.

Bei der Zuweisung wird ein bereits vorhandenes Objekt verwenden, das schon einen Wert haben kann. Die Zuweisung ersetzt dann den vorherigen Wert durch einen neuen Wert. Das Löschen des vorherigen Wertes stellt bei Objekte einer Klasse manchmal eine zusätzliche Operation dar, welche bei der Initialisierung nicht vorkommt.

Die Zuweisung als Kopieroperation

Die Zuweisung stellt das Kopieren eines Wertes (Zustandes) von ihrer rechten zu ihrer linken Seite dar.

Warum muß man (Inhalte) kopieren?

Zuweisungsoperatorfunktionen

Anders als bei den fundamentalen Typen kann bei einem Objekt einer Klasse nicht jedem Objekt ein Wert zugewiesen werden. Vielmehr wird vorausgesetzt, daß die Klasse des Objektes eine passenden Zuweisungsoperatorfunktion enthält, den man in der Dokumentation jener Klasse finden kann. Obwohl bestimmte Formen der Initialisierung und der Zuweisung das Gleichheitszeichen verwenden, kann man also nicht alles, was rechts vom Gleichheitszeichen einer Initialisierung steht, auch rechts vom Gleichheitszeichen einer Zuweisung schreiben, und umgekehrt.

Die Klasse »::std::string« enthält Zuweisungoperatorenfunktionen, deren Details in ihrer Dokumentation beschrieben werden.

::std::string & operator =( ::std::string const & s )
Zuweisung eines ::std::string-Exemplars (kopieren)
::std::string & operator =( ::std::string & & s ) noexcept
Zuweisung eines ::std::string-Exemplars (transportieren)

Auch hier sehen wir wieder die Referenzparameter! (Ein Parameter kann an Stelle des Typs »::std::string« auch den Typ »::std::string const &« oder den Typ »::std::string & &« haben. Für einen solchen Parameter können dieselben Argumente verwendet werden, wie bei einem Parameter vom Typ »::std::string«. An dieser Stelle des Kurses braucht die genaue Bedeutung von Referenzparametern also noch nicht weiter vertieft zu werden.)

Wir zeigen hier ein Beispielprogramm dazu.

main.cpp

#include <iostream> /* ::std::cout */
#include <ostream> /* << */
#include <string> /* ::std::string */

using namespace ::std::literals;

int main()
{ ::std::string const a = "alpha"s;
::std::string
b = a; /* <- Initialisierung */
b = a; /* <- Zuweisung */
::std::cout << b << '\n'; }

::std::cout
alpha

Eine Initialisierung mit einem Gleichheitszeichen »=« ist auch bei einem const-Objekt (wie oben »a«) möglich, während eine Zuweisung an ein const-Objekt nicht erlaubt ist, deswegen muß »b« oben ohne »const« definiert werden.

Dank genialer Erfindungen der C++-Schöpfer, wie besonder Bjarne Stroustrup, kann man Zuweisungen bei Objekten vieler Klassen so verwenden wie Zuweisungen fundamentaler Werte, obwohl bei Objekten von Klassen „hinter den Kulissen“ dabei viel kompliziertere Vorgänge ablaufen als bei Zuweisungen fundamentaler Werte. Was genau bei einer Zuweisung von Objekten von Klassen passiert, wird später noch ausführlicher behandelt werden.

Auch, wenn einem Objekt einer Klasse bei der Definition des Objektes nicht ausdrücklich ein Wert gegeben wurde, gilt die erste Zuweisung eines Wertes an das Objekt doch als Zuweisung und nicht als Initialisierung. Eine Zuweisung liegt immer dann vor, wenn ein Ausdruck mit dem Zuweisungsoperator geschrieben wird. (Die Verwendung des Gleichheitszeichens zur Initialisierung bildet keinen Ausdruck.)

main.cpp

#include <iostream> /* ::std::cout */
#include <ostream> /* << */
#include <string> /* ::std::string */

using namespace ::std::literals;

int main()
{ ::std::string const a = "alpha"s;
::std::string b;
b = a; /* <- Zuweisung */
::std::cout << b << '\n'; }

::std::cout
alpha

Hinzufügende Zuweisungen

Einigen Klassen enthalten auch noch einen speziellen Operator »+=« für eine hinzufügende Zuweisung.

main.cpp

#include <iostream> /* ::std::cout */
#include <ostream> /* << */
#include <string> /* ::std::string */

using namespace ::std::literals;

int main()
{ ::std::string const a = "alpha"s;
::std::string const b;
b += a; /* <- hinzufügende Zuweisung */
b += ", "s; /* <- hinzufügende Zuweisung */
b += b; /* <- hinzufügende Zuweisung */
::std::cout << b << '\n'; }

::std::cout
alpha, alpha,

Exemplarvariablen als Imitationenen fundamentaler Variablen

#include <iostream>

#include <ostream>

#include <string>

int main()

{ ::std::string s{ "abc" };

::std::string t{ "def" };

s = "alpha";

t = s;

::std::cout << s << '\n';

::std::cout << t << '\n'; }

Man möchte, daß die konkrete Wertsemantik-Klasse »::std::string« so einfach verwendet werden kann, wie der fundamentale Typ »int«.

#include <iostream>

#include <ostream>

int main()

{ int s{ 5 };

int t{ 6 };

s = 4;

t = s;

::std::cout << s << '\n';

::std::cout << t << '\n'; }

Veränderung einer Kopie

Wir hatten schon gesagt, daß eine Motivation zum Kopieren im Wunsch liegen kann, die Kopie verändern zu können, ohne das Original dabei zu verändern. Hier zeigen wir nun ein Beispiel dazu.

main.cpp

#include <iostream>

#include <ostream>

#include <string>

#include <initializer_list>

int main()

{ ::std::string const a{ "abc" };

::std::string b;

b = a;

b.push_back( '1' );

::std::cout << a << '\n';

::std::cout << b << '\n'; }

::std::cout

abc

abc1

Ebenfalls erlaubt: »b = "cstring"«

Abgrenzung zur Initialisierung

Bei der Zuweisung können auf der rechten Seite keine Initialisierer, sondern nur Ausdrücke und geschweifte-Klammer-Initialisierer, verwendet werden.

Abgrenzung zur Kopierinitialisierung

Bei einer Zuweisung an ein Objekt mit einer Klasse als Typ enthält das Objekt bereits ein Exemplar einer Klasse, welches durch den Kopiervorgang überschrieben und somit aufgelöst wird. Bei einer Kopierinitialisierung enthält das Objekt aber noch keinen Wert. Daher gibt es bei einer Zuweisung eine zusätzliche Operation, welche bei der Kopierinitialisierung nicht vorkommt: Die Auflösung des bisherigen Objektes.

Typwandlung bei Zuweisung und »explicit«

Der Typ der rechten Seite wird in den Typ der linken Seite gewandelt, wenn es dafür eine nicht-explizite Typwandlungsmöglichkeit gibt.

main.cpp

#include <iostream>
#include <ostream>
#include <string>

int main()
{ ::std::string{ "abc" };
::std::string c = "abc"; /* waere nicht erlaubt bei "explicit" */
::std::string d[ 1 ]={ "abc" }; /* waere nicht erlaubt bei "explicit" */
c = "def"; /* waere nicht erlaubt bei "explicit" */ }

Zuweisungen und geschweifte-Klammer-Initialisierer

Auch ein Initialisierer kann auf der rechten Seite verwendet werden. Dieser wird dann an eine passende Zuweisungsoperatorfunktion übergeben. Dabei können Typwandlungsmöglichkeiten berücksichtigt werden, solange diese nicht »explicit« sind.

main.cpp
#include <initializer_list>
#include <iostream>
#include <ostream>
#include <string>

using namespace ::std::literals;

int main()
{ ::std::string s {};
s ={ 65, 66 };
::std::cout << s << '\n'; /* "AB" */
::std::string t { "abc"s };
s ={ t };
::std::cout << s << '\n'; /* "abc" */ }

Dokumentation der Klasse »::std::string« nach C++  2015, 21.4.2 (vereinfacht)

Wir können unsere Dokumentation der Klasse Klasse »::std::string« nun um die Zuweisungsoperatoren erweitern.

::std::string( ::std::string const & s )
Anlegen eines ::std::string-Exemplars mit dem Text eines anderen ::std::string-Exemplars. (Kopierkonstruktor)
::std::string( ::std::string & & s )
Anlegen eines ::std::string-Exemplars mit dem Text eines anderen ::std::string-Exemplars. (Transportkonstruktor)
::std::string( char const * s );
Anlegen eines ::std::string-Exemplars mit dem Text eines Zeichenfolgenliterals.
::std::string & operator =( ::std::string const & s )
Zuweisung eines ::std::string-Exemplars (kopieren)
::std::string & operator =( ::std::string & & s ) noexcept
Zuweisung eines ::std::string-Exemplars (transportieren)
::std::string & operator +=( ::std::string const & s )
Hinzufügende Zuweisung eines ::std::string-Exemplars
Dokumentation nach n3797, 21.4.2 (vereinfacht)

namespace std
{ class string
{ string();
string( string const str );
string( char const * s );
string( ::std::size_type n, char c );
string( ::std::initializer_list< char >l );

string operator=( string ); }

Übungsaufgaben

/   Übungsaufgabe

In dem folgenden Programm soll der Wert »alpha« aus der Variablen »a« im inneren Block an die Variable »b« zugewiesen werden. Was gibt das Programm aber dann tatsächlich aus?

main.cpp

#include <iostream> /* ::std::cout */
#include <ostream> /* << */
#include <string> /* ::std::string */

using namespace ::std::literals;

int main()
{ ::std::string const a = "alpha"s;
{ ::std::string a;
::std::string b;
b = a;
::std::cout << b << '\n'; }}

Initialisierungslisten

Obwohl Initialisierungslisten nicht immer auf der rechten Seite einer Zuweisung stehen dürfen, erlauben manche Klassen dies.

Seiteninformationen und Impressum   |   Mitteilungsformular  |   "ram@zedat.fu-berlin.de" (ohne die Anführungszeichen) ist die Netzpostadresse von Stefan Ram.   |   Eine Verbindung zur Stefan-Ram-Startseite befindet sich oben auf dieser Seite hinter dem Text "Stefan Ram".)  |   Der Urheber dieses Textes ist Stefan Ram. Alle Rechte sind vorbehalten. Diese Seite ist eine Veröffentlichung von Stefan Ram. Schlüsselwörter zu dieser Seite/relevant keywords describing this page: Stefan Ram Berlin slrprd slrprd stefanramberlin spellched stefanram723307 stefan_ram:723307 Zuweisungen in C++ Stefan Ram, Berlin, and, or, near, uni, online, slrprd, slrprdqxx, slrprddoc, slrprd723307, slrprddef723307, PbclevtugFgrsnaEnz Erklärung, Beschreibung, Info, Information, Hinweis,

Der Urheber dieses Textes ist Stefan Ram. Alle Rechte sind vorbehalten. Diese Seite ist eine Veröffentlichung von Stefan Ram.
https://www.purl.org/stefan_ram/pub/zuweisungen_c++