Zeiger und Referenzen
Teil des Abschnitts Objektorientierte Programmierung der C++-Journey von Coddy. Lektion 13 von 104.
Nachdem du Stack- und Heap-Speicher verstanden hast, sehen wir uns nun die Werkzeuge an, mit denen du direkt mit Speicheradressen arbeiten kannst: pointer und references.
Ein Zeiger speichert die Speicheradresse einer anderen Variablen. Du deklarierst ihn mit * und erhältst eine Adresse mit &.
int value = 42;
int* ptr = &value; // ptr hält die Adresse von value
std::cout << ptr; // Gibt die Speicheradresse aus
std::cout << *ptr; // Dereferenzierung: gibt 42 ausEine Referenz ist ein Alias für eine vorhandene Variable. Sobald sie gebunden ist, verweist sie immer auf diese Variable. Du deklarierst sie mit &.
int value = 42;
int& ref = value; // ref ist ein Alias für value
ref = 100; // Ändert value zu 100
std::cout << value; // Gibt 100 ausWichtige Unterschiede:
| Zeiger | Referenzen |
|---|---|
| Können null sein | Müssen initialisiert werden |
| Können neu zugewiesen werden | Können nicht neu gebunden werden |
* verwenden, um auf den Wert zuzugreifen | Direkt auf den Wert zugreifen |
| Können auf nichts pointen | Immer gültig |
Beide sind unerlässlich, um Objekte effizient an Funktionen zu übergeben, ohne sie zu kopieren, und um mit heap-allokiertem Speicher zu arbeiten. Referenzen sind sicherer und einfacher, während Zeiger mehr Flexibilität bieten, wenn du sie neu zuweisen oder auf null prüfen musst.
Aufgabe
EinfachErstellen wir ein einfaches System zur Manipulation von Werten, das veranschaulicht, wie sich Pointer und Referenzen beim Ändern von Daten unterschiedlich verhalten.
Du erstellst zwei Dateien, um deinen Code zu organisieren:
ValueOps.h: Definiere drei Funktionen, die Integer-Werte auf unterschiedliche Weise ändern:doubleByPointer(int* ptr): übernimmt einen Pointer und verdoppelt den Wert, auf den er zeigttripleByReference(int& ref): übernimmt eine Referenz und verdreifacht den WertswapValues(int* a, int* b): übernimmt zwei Pointer und vertauscht die Werte, auf die sie zeigen
main.cpp: Lies zwei Integer aus der Eingabe ein und demonstriere anschließend sowohl Pointer als auch Referenzen:- Gib die ursprünglichen Werte aus:
"Original: <first> <second>" - Verwende
doubleByPointerfür den ersten Wert und gib anschließend aus:"After double: <first>" - Verwende
tripleByReferencefür den zweiten Wert und gib anschließend aus:"After triple: <second>" - Verwende
swapValues, um beide Werte zu vertauschen, und gib anschließend aus:"After swap: <first> <second>"
- Gib die ursprünglichen Werte aus:
Denke beim Aufrufen von Funktionen mit Pointern daran, den Adressoperator (&) zu verwenden, um die Adresse der Variable zu übergeben. Referenzen funktionieren auf natürlichere Weise; übergib die Variable einfach direkt.
Binde deine Header-Datei in main.cpp mit #include "ValueOps.h" ein.
Probier es selbst
#include <iostream>
#include "ValueOps.h"
using namespace std;
int main() {
// Zwei Ganzzahlen von der Eingabe lesen
int first, second;
cin >> first;
cin >> second;
// Originale Werte ausgeben
cout << "Original: " << first << " " << second << endl;
// TODO: Verwende doubleByPointer auf den ersten Wert (Adresse mit & übergeben)
// TODO: Nach dem Verdoppeln ausgeben
// TODO: Verwende tripleByReference auf den zweiten Wert (Variable direkt übergeben)
// TODO: Nach dem Verdreifachen ausgeben
// TODO: Verwende swapValues, um beide Werte zu tauschen (Adressen mit & übergeben)
// TODO: Nach dem Tauschen ausgeben
return 0;
}
Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Alle Lektionen in Objektorientierte Programmierung
1Grundlagen der OOP
Externe DateienC++ Build & KompilierungHeader-Dateien & QuelldateienNamespaces & GültigkeitsbereichEinführung in OOP mit C++Klassen vs. ObjekteDer „this“-ZeigerMethoden (Member-Funktionen)Attribute (Datenmember)Grundlagen zu Ctors & DtorsRückblick – Einfacher Taschenrechner4Klassenattribute
Instanz- vs. statische MemberGetter und SetterConst-MemberfunktionenMutable-SchlüsselwortStatische Methoden und VariablenFriend-Funktionen und -KlassenZusammenfassung – Bankkontoverwaltung7Vererbung
Grundlagen der VererbungZugriffsebenen bei der VererbungAufrufreihenfolge von Ctor & DtorÜberschreiben von MethodenVirtuelle Funktionen & VTableMehrfachvererbungVirtuelle VererbungRückblick – Mitarbeiterhierarchie2Speicherverwaltung
Stack- vs. Heap-SpeicherZeiger und ReferenzenDynamischer Speicher (new/delete)Intelligente Zeiger in C++RAII in C++Rückblick – Dynamischer Array-Manager5Kapselung
Zugriffsbezeichner in C++Zugriffsbezeichner im DetailInformationsverbergungStruct vs. KlasseVerschachtelte und innere KlassenWiederholung – Studierendenverwaltungssystem8Polymorphie
Polymorphie zur Compilezeit vs. LaufzeitFunktionsüberladungVirtuelle Funktionen erneut betrachtetRein virtuelle FunktionenAbstrakte KlassenInterface-Design in C++Dynamic Casting & RTTIRückblick – Shape-Calculator3Konstruktoren & Destruktoren
StandardkonstruktorParametrisierter KonstruktorKopierkonstruktorMove-KonstruktorKonstruktor-InitialisierungslistenDelegierende KonstruktorenDestruktor im DetailDrei-/Fünf-/Null-RegelZusammenfassung – String-Klasse6Operatorüberladung
Einführung in die OperatorüberladungArithmetische OperatorüberladungVergleichsoperatorüberladungStream-OperatorenZuweisungsoperatorüberladungÜberladung der Operatoren [] und ()TypkonvertierungsoperatorenWiederholung – Matrix-Klasse9Templates
FunktionstemplatesKlassen-TemplatesTemplate-SpezialisierungVariadische TemplatesGrundlagen zu SFINAE und Type TraitsRückblick – Generischer ContainerÜbe selbstständig: Online-C++-Compiler