Lassen Sie mich versuchen, auch darauf zu antworten.
Zeiger sind ähnlich wie Referenzen. Mit anderen Worten, es handelt sich nicht um Kopien, sondern vielmehr um eine Möglichkeit, auf den Originalwert zu verweisen.
Vor allem an einem Ort, wo Sie in der Regel häufig Zeiger verwenden müssen, ist der Umgang mit eingebetteter Hardware. Vielleicht müssen Sie den Zustand eines digitalen IO-Pins umschalten. Vielleicht verarbeiten Sie einen Interrupt und müssen einen Wert an einem bestimmten Speicherort speichern. Sie verstehen sicher, worum es geht. Wenn Sie jedoch nicht direkt mit Hardware arbeiten und sich nur fragen, welche Typen Sie verwenden sollten, lesen Sie weiter.
Warum Zeiger anstelle von normalen Variablen verwenden? Die Antwort wird klarer, wenn Sie es mit komplexen Typen wie Klassen, Strukturen und Arrays zu tun haben. Wenn Sie eine normale Variable verwenden würden, könnten Sie am Ende eine Kopie erstellen (Compiler sind in einigen Situationen schlau genug, um dies zu verhindern, und auch C++11 hilft, aber wir werden das Thema vorerst meiden).
Was passiert jedoch, wenn Sie den Originalwert ändern möchten? Sie könnten etwas wie dies verwenden:
MyType a; //lassen Sie uns vorerst ignorieren, was MyType tatsächlich ist.
a = modify(a);
Das funktioniert einwandfrei und wenn Sie nicht genau wissen, warum Sie Zeiger verwenden, sollten Sie sie nicht verwenden. Vorsicht vor dem Argument "sie sind wahrscheinlich schneller". Führen Sie Ihre eigenen Tests durch und wenn sie tatsächlich schneller sind, verwenden Sie sie.
Angenommen, Sie lösen ein Problem, bei dem Sie Speicher zuweisen müssen. Wenn Sie Speicher zuweisen, müssen Sie diesen auch freigeben. Die Speicherzuweisung kann erfolgreich sein oder auch nicht. Hier kommen Zeiger nützlich ins Spiel - sie ermöglichen es Ihnen, auf das Vorhandensein des Objekts zu überprüfen, für das Sie Speicher zugewiesen haben, und sie ermöglichen es Ihnen, auf das Objekt zuzugreifen, für das der Speicher zugewiesen wurde, indem Sie den Zeiger dereferenzieren.
MyType *p = NULL; //leerer Zeiger
if(p)
{
//wir kommen nie hierhin, weil der Zeiger auf nichts zeigt
}
//lassen Sie uns jetzt etwas Speicher zuweisen
p = new MyType[50000];
if(p) //wenn der Speicher zugewiesen wurde, wird dieser Test bestehen
{
//wir können etwas mit unserem zugewiesenen Array machen
for(size_t i=0; i!=50000; i++)
{
MyType &v = *(p+i); //eine Referenz auf das i-te Objekt erhalten
//etwas damit tun
//...
}
delete[] p; //wir sind fertig. Speicher freigeben
}
Dies ist der Schlüssel, warum Sie Zeiger verwenden würden - Referenzen setzen voraus, dass das von Ihnen referenzierte Element bereits vorhanden ist. Ein Zeiger nicht.
Ein weiterer Grund, warum Sie Zeiger verwenden würden (oder zumindest enden würden, damit umzugehen), ist, dass sie ein Datentyp sind, der vor Referenzen existierte. Daher werden Sie feststellen, dass viele dieser Bibliotheken Zeiger überall verwenden, einfach wegen ihrer langen Existenz (viele wurden vor C++ geschrieben).
Wenn Sie keine Bibliotheken verwenden, könnten Sie Ihren Code so entwerfen, dass Sie sich von Zeigern fernhalten, aber da Zeiger einer der grundlegenden Typen der Sprache sind, desto schneller Sie sich daran gewöhnen, sie zu verwenden, desto portabler wären Ihre C++-Fähigkeiten.
Aus Sicht der Wartbarkeit sollte ich auch erwähnen, dass wenn Sie Zeiger verwenden, Sie entweder auf ihre Gültigkeit testen und den Fall behandeln müssen, wenn sie ungültig sind, oder einfach davon ausgehen, dass sie gültig sind und akzeptieren müssen, dass Ihr Programm abstürzt oder schlimmer wird, WENN diese Annahme gebrochen wird. Anders ausgedrückt, Ihre Wahl bei Zeigern besteht darin, entweder Codekomplexität einzuführen oder mehr Wartungsaufwand zu betreiben, wenn etwas bricht und Sie versuchen, einen Fehler nachzuvollziehen, der zu einer ganzen Klasse von Fehlern gehört, die Zeiger einführen, wie z.B. Speicherkorruption.
Wenn Sie den gesamten Code kontrollieren, bleiben Sie von Zeigern fern und verwenden stattdessen Referenzen, halten Sie diese const, wenn Sie können. Dadurch werden Sie gezwungen, über die Lebensdauer Ihrer Objekte nachzudenken, und Ihr Code wird einfacher zu verstehen sein.
Denken Sie nur an diesen Unterschied: Eine Referenz ist im Grunde ein gültiger Zeiger. Ein Zeiger ist nicht immer gültig.
Sage ich also, dass es unmöglich ist, eine ungültige Referenz zu erstellen? Nein. Es ist vollkommen möglich, weil C++ Ihnen fast alles erlaubt. Es ist jedoch schwieriger, dies unbeabsichtigt zu tun, und Sie werden erstaunt sein, wie viele Fehler unbeabsichtigt sind :)
8 Stimmen
Bereits diskutiert unter dieser Frage Hoffe, das hilft!
0 Stimmen
Eine weitere Diskussion über Pointer hier.
4 Stimmen
Für eine Liste von Büchern, siehe stackoverflow.com/questions/388242/…. Nach Java fand ich Accelerated C++ sehr nützlich.
265 Stimmen
Wir verwenden Zeiger, weil es einfacher ist, jemandem die Adresse zu Ihrem Zuhause zu geben, als jedem eine Kopie Ihres Zuhauses zu geben.
28 Stimmen
@RishiDua Das ist die beste Erklärung eines Zeigers, auf die ich je gestoßen bin. Danke dafür, es hat mein Verständnis erhöht :)
3 Stimmen
Pointern können auch verwendet werden, wenn Sie mehr als einen Wert/Objekt zurückgeben möchten.
2 Stimmen
Unterstützt von Rishi Dua, sind die Links in den obigen Kommentaren wie Zeiger. Stellen Sie sich vor, wenn sie stattdessen ganze Artikel oder Diskussionen hier kopiert und eingefügt hätten. Wir würden schnell "Platzmangel" auf der Seite haben.
0 Stimmen
@RishiDua wenn ich diesen Satz nur gesehen hätte, als ich anfing, C zu lernen... so viel Zeit gespart.. Danke :)