Lassen Sie mich auch versuchen, dies zu beantworten.
Zeiger ähneln Referenzen. Mit anderen Worten, es handelt sich nicht um Kopien, sondern um eine Möglichkeit, auf den ursprünglichen Wert zu verweisen.
Ein Ort, an dem Sie normalerweise häufig Zeiger verwenden müssen, ist der Umgang mit eingebetteter Hardware . Möglicherweise müssen Sie den Status eines digitalen E / A-Pins umschalten. Möglicherweise verarbeiten Sie einen Interrupt und müssen einen Wert an einem bestimmten Ort speichern. Du bekommst das Bild. Wenn Sie sich jedoch nicht direkt mit Hardware befassen und sich nur fragen, welche Typen Sie verwenden sollen, lesen Sie weiter.
Warum Zeiger im Gegensatz zu normalen Variablen verwenden? Die Antwort wird klarer, wenn Sie mit komplexen Typen wie Klassen, Strukturen und Arrays arbeiten. Wenn Sie eine normale Variable verwenden, erstellen Sie möglicherweise eine Kopie (Compiler sind intelligent genug, um dies in einigen Situationen zu verhindern, und C ++ 11 hilft auch, aber wir werden uns vorerst von dieser Diskussion fernhalten).
Was passiert nun, wenn Sie den ursprünglichen Wert ändern möchten? Sie könnten so etwas verwenden:
MyType a; //let's ignore what MyType actually is right now.
a = modify(a);
Das wird gut funktionieren und wenn Sie nicht genau wissen, warum Sie Zeiger verwenden, sollten Sie sie nicht verwenden. Hüten Sie sich vor dem Grund "sie sind wahrscheinlich schneller". Führen Sie Ihre eigenen Tests durch und verwenden Sie sie, wenn sie tatsächlich schneller sind.
Angenommen, Sie lösen ein Problem, bei dem Sie Speicher zuweisen müssen. Wenn Sie Speicher zuweisen, müssen Sie die Zuordnung aufheben. Die Speicherzuweisung kann erfolgreich sein oder nicht. Hier kommen Zeiger zum Einsatz - Sie können die Existenz des von Ihnen zugewiesenen Objekts testen und auf das Objekt zugreifen, für das der Speicher zugewiesen wurde, indem Sie die Referenzierung des Zeigers aufheben.
MyType *p = NULL; //empty pointer
if(p)
{
//we never reach here, because the pointer points to nothing
}
//now, let's allocate some memory
p = new MyType[50000];
if(p) //if the memory was allocated, this test will pass
{
//we can do something with our allocated array
for(size_t i=0; i!=50000; i++)
{
MyType &v = *(p+i); //get a reference to the ith object
//do something with it
//...
}
delete[] p; //we're done. de-allocate the memory
}
Dies ist der Schlüssel, warum Sie Zeiger verwenden würden - Referenzen setzen voraus, dass das Element, auf das Sie verweisen, bereits vorhanden ist . Ein Zeiger nicht.
Der andere Grund, warum Sie Zeiger verwenden würden (oder zumindest damit umgehen müssen), ist, dass es sich um einen Datentyp handelt, der vor Referenzen vorhanden war. Wenn Sie also Bibliotheken verwenden, um die Dinge zu tun, von denen Sie wissen, dass sie besser sind, werden Sie feststellen, dass viele dieser Bibliotheken überall Zeiger verwenden, einfach weil sie schon so lange da sind (viel) von ihnen wurden vor C ++ geschrieben).
Wenn Sie keine Bibliotheken verwendet haben, können Sie Ihren Code so gestalten, dass Sie sich von Zeigern fernhalten. Da Zeiger jedoch einer der Grundtypen der Sprache sind, gilt: Je schneller Sie sich mit ihnen vertraut machen, desto mehr tragbar wären Ihre C ++ - Kenntnisse.
Unter dem Gesichtspunkt der Wartbarkeit sollte ich auch erwähnen, dass Sie bei Verwendung von Zeigern entweder deren Gültigkeit prüfen und den Fall behandeln müssen, wenn sie nicht gültig sind, oder einfach davon ausgehen, dass sie gültig sind, und die Tatsache akzeptieren, dass Ihre Programm wird abstürzen oder schlimmer, wenn diese Annahme gebrochen ist. Anders ausgedrückt, Ihre Wahl mit Zeigern besteht darin, entweder Code-Komplexität oder mehr Wartungsaufwand einzuführen, wenn etwas kaputt geht und Sie versuchen, einen Fehler aufzuspüren, der zu einer ganzen Klasse von Fehlern gehört, die Zeiger verursachen, wie z. B. Speicherbeschädigung.
Wenn Sie also Ihren gesamten Code kontrollieren, halten Sie sich von Zeigern fern und verwenden Sie stattdessen Verweise. Halten Sie diese konstant, wenn Sie können. Dies zwingt Sie dazu, über die Lebenszeiten Ihrer Objekte nachzudenken, und führt dazu, dass Ihr Code leichter verständlich bleibt.
Denken Sie nur an diesen Unterschied: Eine Referenz ist im Wesentlichen ein gültiger Zeiger. Ein Zeiger ist nicht immer gültig.
Also sage ich, dass es unmöglich ist, eine ungültige Referenz zu erstellen? Nein, es ist absolut möglich, weil Sie mit C ++ fast alles machen können. Es ist nur schwieriger, dies unbeabsichtigt zu tun, und Sie werden erstaunt sein, wie viele Fehler unbeabsichtigt sind :)