Referenzen vs. Zeiger
Zentrale Unterschiede: Nullbarkeit, erneutes Binden, Indirektion und Speichersemanik.
In C++ gibt es zwei wichtige Konzepte beim Arbeiten mit Daten: Pointer (Zeiger) und Referenzen. Beide werden verwendet, um auf eine andere Variable zu “verweisen”; sie unterscheiden sich jedoch in ihrer Funktionsweise, im Speicherverhalten und in der Sicherheit. In diesem Artikel werden wir Pointer und Referenzen, ihre Unterschiede und Anwendungsbereiche mit Beispielen betrachten.
1. Was ist ein Pointer?
Ein Pointer ist eine spezielle Variable, die eine Speicheradresse speichert. Mit Pointern kann man indirekt auf den Wert einer anderen Variable zugreifen.
#include <iostream>
using namespace std;
int main() {
int zahl = 10;
int *ptr = &zahl; // die Adresse von 'zahl' wird dem Pointer zugewiesen
cout << "Wert von zahl: " << zahl << endl;
cout << "Wert von ptr (Adresse): " << ptr << endl;
cout << "Wert, auf den ptr zeigt: " << *ptr << endl;
*ptr = 20; // Wert über den Pointer geändert
cout << "Neuer Wert von zahl: " << zahl << endl;
return 0;
}
Hier greift *ptr (Dereferenzierung) auf den Wert der Variable zu, auf die der Pointer zeigt.
Da Pointer direkt Speicheradressen manipulieren können, sind sie sehr mächtig – aber auch gefährlich, wenn sie falsch verwendet werden.
2. Was ist eine Referenz?
Eine Referenz ist ein “Alias” für eine andere Variable. Im Gegensatz zu einem Pointer speichert sie keine Adresse, sondern teilt direkt denselben Speicherbereich. Eine Referenz muss beim Deklarieren sofort an eine Variable gebunden werden.
#include <iostream>
using namespace std;
int main() {
int x = 50;
int &ref = x; // ref ist eine Referenz auf x
cout << "x: " << x << ", ref: " << ref << endl;
ref = 100; // Wert von x über die Referenz geändert
cout << "Neuer Wert von x: " << x << endl;
return 0;
}
In diesem Beispiel teilt ref tatsächlich denselben Speicherort wie x.
Wenn einer geändert wird, ändert sich der andere automatisch.
3. Unterschiede zwischen Pointer und Referenzen
Die folgende Tabelle zeigt die wichtigsten Unterschiede:
| Eigenschaft | Pointer | Referenz |
|---|---|---|
| Deklaration | int *p = &x; |
int &r = x; |
| Speichert Adresse? | Ja, speichert eine Speicheradresse | Nein, direkt mit Variable verknüpft |
| Kann NULL sein? | Ja, kann nullptr sein |
Nein, muss immer eine Variable referenzieren |
| Neu zuweisbar? | Ja, kann auf eine andere Adresse zeigen | Nein, einmal gebunden nicht änderbar |
| Dereferenzierung | Mit *p zugänglich |
Direkt verwendbar |
| Speicherverwaltung | Vom Programmierer gesteuert (new/delete) | Automatisch verwaltet |
| Performance | Indirekter Zugriff | Direkter Zugriff (schneller) |
4. Speicheransicht
So verhalten sich Pointer und Referenzen im Speicher:
int x = 10;
int *ptr = &x;
int &ref = x;
cout << "&x: " << &x << endl;
cout << "ptr: " << ptr << endl;
cout << "&ref: " << &ref << endl;
Beispielhafte Speicheranordnung:
Variable | Adresse | Wert
x | 0x61ff0c | 10
ptr | 0x61ff08 | 0x61ff0c
ref | 0x61ff0c | 10
Wie man sieht, nutzt ref denselben Speicher wie x,
während ptr seine eigene Adresse hat und eine andere (die von x) speichert.
5. Pointer und Referenzen in Funktionen
Pointer und Referenzen können als Parameter übergeben werden, um externe Variablen zu verändern.
Mit Pointer
void Erhoehe(int *p) {
(*p)++;
}
int main() {
int zahl = 5;
Erhoehe(&zahl);
cout << zahl; // 6
}
Mit Referenz
void Erhoehe(int &r) {
r++;
}
int main() {
int zahl = 5;
Erhoehe(zahl);
cout << zahl; // 6
}
Beide Methoden liefern dasselbe Ergebnis, aber die Verwendung von Referenzen ist einfacher und sicherer.
6. const Referenzen
Wenn man verhindern möchte, dass eine Referenz den Wert ändert,
kann man das Schlüsselwort const verwenden.
void Ausgabe(const string &text) {
cout << text << endl;
}
int main() {
string nachricht = "C++ ist großartig!";
Ausgabe(nachricht);
}
const &-Referenzen ermöglichen es, große Objekte ohne Kopie sicher an Funktionen zu übergeben,
was auch die Performance verbessert.
7. Kombination von Pointer und Referenzen
Manchmal werden Pointer und Referenzen gemeinsam verwendet. Zum Beispiel kann man eine Referenz auf einen Pointer erstellen.
#include <iostream>
using namespace std;
int main() {
int x = 5;
int *p = &x;
int *&refAufPointer = p; // Referenz auf Pointer
*refAufPointer = 10;
cout << x << endl; // 10
}
Diese Struktur mag kompliziert erscheinen, ist aber besonders bei dynamischem Speicher und Funktionsparametern nützlich.
8. Beste Anwendungsfälle
- Pointer → dynamische Speicherverwaltung (
new/delete), Arrays, Low-Level-Operationen - Referenzen → Funktionsparameter, Operatorüberladung, Objektfreigabe
In modernem C++ sollte man vorzugsweise Referenzen oder
Smart Pointer (z. B. std::unique_ptr) anstelle von rohen Pointern verwenden.
9. TL;DR
- Ein Pointer speichert eine Adresse; eine Referenz ist ein Alias für eine Variable.
- Ein Pointer kann
nullptrsein; eine Referenz nicht. - Ein Pointer kann neu zugewiesen werden; eine Referenz bleibt fest gebunden.
*pgreift auf den Wert zu, auf den der Pointer zeigt; Referenzen werden direkt verwendet.const &-Referenzen übergeben große Objekte sicher ohne Kopie.- Pointer → für Speicherverwaltung; Referenzen → für einfachen, sicheren Zugriff.
- Alle Beispiele können in Visual Studio 2022 oder GCC 11+ ausgeführt werden.