C++ Grundkurs

Referenzen

LinkedIn Learning kostenlos und unverbindlich testen!

Jetzt testen Alle Abonnements anzeigen
Das Verhalten von Referenzen entspricht dem von konstanten Zeigern und stellt alternative Namen auf Variablen dar. Die modernen Versionen von C++ unterscheiden zwischen zwei unterschiedlichen Referenzen.
07:51

Transkript

In dieser Lektion werde ich Ihnen Referenzen vorstellen. Insbesondere werde ich Ihnen vorstellen, dass Referenzen konstanten Zeigern sehr ähnlich sind. Darüber hinaus werde ich noch eine Unterscheidung machen zwischen Lvalue- und Rvalue-Referenzen. Die Unterscheidung, die im modernen C++ relativ wichtig ist. Um Lvalues- und Rvalues-Referenzen zu erklären, muss ich erst erklären, was ein Lvalue ist. Referenzen sind alternative Namen für Variablen. Sie werden erklärt, indem der Variable das Und-Symbol (&) vorangestellt wird. Das sehen Sie hier. Ich habe hier eine i vom Typ int initialisiert mit dem Wert 20. Ich erkläre eine Referenz auf i, indem ich int & Ref schreibe. Das ist eine Referenz auf i. Das Entscheidende ist, dass Referenzen immer per Definition initialisiert werden müssen, da eine Referenz immer auf einen Wert verweisen muss. Er muss immer etwas referenzieren. Das verdeutlicht auch schon die Verwandtschaft von der Referenz zum konstanten Zeiger. Eine Referenz referenziert immer irgendwas. Das ist also eine Interaktion wie beim Zeiger. Dann referenziert die Referenz immer das Gleiche, immer die gleiche Variable. Von daher ist sie wie ein konstanter Zeiger. Entscheidend ist auch noch, dass die Referenz nur mit einer Variablen des gleichen Typs initialisiert werden kann. Schauen Sie hier. Hier habe ich ein int und ich habe hier eine iRef. Wo Referenzen sehr interessant sind, sind Referenzen im Zusammenhang mit Funktionsparametern. Weil Ihnen Referenzen erlauben, das Funktionsargument direkt zu adressieren. Wenn Sie die Referenz nicht konstant machen, können Sie im Funktionskörper den Wert verändern. Wenn Sie die Referenz konstant machen, können Sie nur lesend - also nicht modifizierend - darauf zugreifen. Das Schöne an den Referenzen ist, da Sie durch die Referenz eine Variable außerhalb ihres Funktionskörpers referenzieren, verhindern Sie natürlich auch das Kopieren. Hier ein klassisches Beispiel. Meine Funktion xchg. Die erwartet zwei Referenzen auf int. Eine habe ich x und eine habe ich y genannt. Dadurch dass das zwei Referenzen sind, sind die Veränderungen, die ich mit x und y im Körper der der Funktion xchg mache, außerhalb von der Funktion in xy sichtbar. Jetzt komme ich auf die R- und die Lvalue-Referenzen. Aber da muss ich erst ausholen und erzähle einmal, was ein Rvalue ist. Ein Rvalue ist ein temporäres Objekt. Also ein Objekt, das nur eine ganz kurze Lebenszeit hat. Es ist - so kann man es sich auch vorstellen - ein Objekt ohne Namen. Einfach etwas, was der Compiler schnell mal erzeugt und dann wieder wegwirft, aber er nicht weiter braucht. Interessant ist auch, es ist ein Objekt, von dem sich die Adresse nicht bestimmen lässt. Das sind Rvalues. Ich zeige Ihnen gleich ein paar Beispiele. Der ganze Rest sind Lvalues. Die entscheidende Beobachtung ist jetzt aber, dass Lvalues, dessen Variablen int a=5 - a ist ein Lvalue -, dass Lvalue nur Lvalue-Referenzen, Rvalues an konstante Lvalue-Referenzen oder Rvalue-Referenzen gebunden werden können. MyData: myData ist eine Lvalue. Das Objekt hat einen Namen. Es heißt MyData. Es hat eine definierte Lebenszeit. Es ist nicht nur temporär und Sie können vom MyData auch die Adresse bestimmen. Das ist ein Lvalue. So ein Lvalue kann ich nehmen, um eine Lvalue-Referenz - Sie sehen die Referenz mit einem Und-Symbol - zu initialisieren. Wenn ich MyData, das ist ein Struct, aufrufe und hier temporäre in Objekt instanziiere, dann lebt das Objekt nur für diesen kurzen Lebenszeitpunkt. Das ist ein vollkommen temporäres Objekt. Von diesem Objekt können Sie auch nicht die Adresse bestimmen. Dieses Objekt hat keinen Namen. Sie haben es nirgends zugewiesen. Das ist jetzt ein Rvalue und dem können Sie einer Rvalue-Referenz zuweisen. Jetzt kommt der letzte Schritt: von den L- und Rvalues zu den L- und Rvalue-Referenzen. Lvalue-Referenzen werden durch ein &-Symbol deklariert und können auf der linken Seite einer Zuweisung stehen. Das ist entscheidend. Sie können einer Lvalue-Referenz etwas zuweisen, weil das nicht temporär ist, weil es einen Namen hat. Rvalue-Referenzen werden durch zwei &&-Symbole deklariert, stehen in der Regel auf der rechten Seite einer Zuweisung und - das ist das Entscheidende - sind die Grundlage für die Move-Semantik. Die Data Move-Semantik ist es, dass Sie temporäre Variablen, wenn Sie von a nach b kopieren, nicht kopieren müssen, sondern verschieben können, weil Sie wissen, dass der Ursprung dieser Kopieraktion vollkommen temporär ist, keine lange Gültigkeit hat. Jetzt zeige ich Ihnen das in der Anwendung. Hier gibt es eine Funktion xchg. Die haben Sie vorher schon gesehen. Die Funktion xchg nimmt zwei int-Werte an, jeweils per Referenz, und tauscht die Werte aus im klassischen Dreieckstausch. Hier eine ganz einfache Klasse. Die Klasse heißt MyData und die hat einen leeren Funktionskörper. Ich habe struct verwendet. Mehr äquivalent in diesem Sinne. Dann zwei Funktionen: Funktion 1 und Funktion 2. Beide heißen Funktion. Der feine Unterschied ist, dass die erste Funktion eine Lvalue-Referenz annimmt, ein &, und die zweite Funktion eine Rvalue-Referenz annimmt, zwei &&-Symbole. Die erste gibt dann zurück lvalue reference, die zweite gibt dann zurück, rvalue reference. Jetzt zeige ich Ihnen Referenzen in der Anwendung. Hier habe ich eine Variable i vom Typ int, initialisiert mit dem Wert 2011, und durch das &-Symbol habe ich eine Referenz auf i. D. h., das r verweist auf den gleichen Wert wie das i hier oben. Das sehen Sie dadurch, dass ich mir den Wert von r ausgeben lassen kann. Ich kann den Wert von i, wohlgemerkt , nicht von r, auf 2014 setzen und mir noch einmal den Wert r ausgeben lassen, und Sie sehen, der Wert von r hat sich von 2011 auf 2014 hier geändert. Weiter geht es mit Referenzen. Ich habe hier zwei Werte five und six, mit den Werten 5 und 6. Ich gebe sie aus: 5, 6. Jetzt verwende ich die Funktion von oben xchg, die die beiden Werte vertauscht und Sie sehen, danach wird aus 5 und 6 und aus 6 und 5. Warum funktioniert das? Ganz einfach, weil ich die Werte in xchg per Referenz annehme. D. h., Veränderungen, die ich in diesem Funktionskörper mache, sind auch außerhalb des Funktionskörpers sichtbar, weil ich in der Funktion xchg auf die Werte five und six zugreife. Jetzt komme ich noch auf die Lvalue- und Rvalue-Referenzen. Ich instanziiere ein Objekt vom Typ myData. Sie wissen, myData ist ein ganz einfacher Datentyp. Wenn ich jetzt die Funktion myData aufrufe mit einem Lvalue, dann bekomme ich heraus das Ergebnis lvalue reference, weil dieser Lvalue bewirkt, dass die Funktion hier oben von der überladenen Funktion verwendet wird, die eine Lvalue-Referenz annimmt. Die gibt eben lvalue reference aus. Wenn ich aber jetzt ein temporäres Objekt hier anlege, MyData, existiert nur genauso lange, bis dieser Ausdruck hier ausgewertet ist, der Funktionsaufruf. Wenn ich also MyData hier in place instanziiere, dann ist das vollkommen ein temporäres Objekt. Damit ist es ein Objekt, von dem ich nicht die Adresse bestimmen kann. Damit ist es natürlich auch ein Objekt, das keinen Namen hat und damit ist es per Definition ein temporäres Objekt. D. h., es ist ein Rvalue. D. h. wiederum, dass die Funktion, die eine Rvalue-Referenz annimmt, dieses Argument annimmt, und als Ergebnis erhalte ich hier rvalue reference. In dieser Lektion habe ich Ihnen Referenzen vorgestellt. Insbesondere habe ich Ihnen gezeigt, dass Referenzen konstanten Zeigern sehr ähnlich sind. Dann ging ich noch auf das weiterführende Konzept der Lvalue- und Rvalue-Referenzen ein. Lvalue- und Rvalue-Referenzen setzen voraus, dass Sie Lvalues und Rvalues kennen, und Lvalues sind einfach im Kopf zu behalten. Rvalues sind einfach all die Werte, die temporär sind, keinen Namen haben, von denen Sie die Adresse nicht bestimmten können. Der ganze Rest ist Lvalue. Die Regel ist, wenn Sie eine Funktion haben, die sowohl Lvalue- als auch Rvalue-Referenzen annehmen kann, dann bindet Lvalue nur an eine Lvalue-Referenz, und ein Rvalue kann eine konstante Lvalue-Referenz binden oder eine Rvalue-Referenz.

C++ Grundkurs

Steigen Sie in die mächtige Programmiersprache C++ ein und lernen Sie dabei alle wichtigen Funktionen mit Anwendungsbeispielen kennen.

8 Std. 14 min (147 Videos)
Derzeit sind keine Feedbacks vorhanden...

Dieser Online-Kurs ist als Download und als Streaming-Video verfügbar. Die gute Nachricht: Sie müssen sich nicht entscheiden - sobald Sie das Training erwerben, erhalten Sie Zugang zu beiden Optionen!

Der Download ermöglicht Ihnen die Offline-Nutzung des Trainings und bietet die Vorteile einer benutzerfreundlichen Abspielumgebung. Wenn Sie an verschiedenen Computern arbeiten, oder nicht den ganzen Kurs auf einmal herunterladen möchten, loggen Sie sich auf dieser Seite ein, um alle Videos des Trainings als Streaming-Video anzusehen.

Wir hoffen, dass Sie viel Freude und Erfolg mit diesem Video-Training haben werden. Falls Sie irgendwelche Fragen haben, zögern Sie nicht uns zu kontaktieren!