Ich habe C seit Jahren programmiert, hauptsächlich in einer eingebetteten Umgebung, und habe ein perfektes mentales Modell von Zeigern - ich muss nicht explizit darüber nachdenken, wie man sie benutzt, bin mit der Zeigerarithmetik 100% vertraut , Arrays von Zeigern, Zeigern zu Zeigern usw.
Ich habe sehr wenig C ++ geschrieben und habe wirklich keine gute Idee, über Referenzen nachzudenken. Mir wurde in der Vergangenheit geraten, "sie als Zeiger zu betrachten, die nicht NULL sein können", aber diese Frage zeigt, dass das alles noch lange nicht alles ist.
Also für erfahrenere C ++ Programmierer - wie denken Sie über Referenzen? Denkst du an sie als eine spezielle Art von Zeiger oder als ihre eigene Sache? Was ist ein guter Weg für einen C-Programmierer, um das Konzept zu verstehen?
Ich habe mich daran gewöhnt, über Referenzen als Alias für das Hauptobjekt nachzudenken.
BEARBEITEN (aufgrund einer Anfrage in Kommentaren):
Ich dachte über die Art von Aliasing nach, weil es sich genau wie die ursprüngliche Variable verhält, ohne dass eine zusätzliche Manipulation erforderlich ist, um die referenzierte Variable zu beeinflussen.
Wenn ich einen Zeiger im Code sehe (als lokale Variable in einer Funktion oder als Mitglied einer Klasse), muss ich an
denkenIch muss nicht an etwas denken, wenn es eine Referenz ist, es ist jemand anderes Problem (dh denke an eine Referenz als SEP-Feld für einen Zeiger)
P.S. Ja, es ist wahrscheinlich immer noch mein Problem, gerade nicht jetzt
Ich mag die "immer gültige" Ansicht nicht allzu gern, da Referenzen ungültig werden können, z. B.
%Vor%Also, ich denke an Referenzen als nicht-wiederverwertbar (das heißt, Sie können nicht das Ziel einer Referenz ändern, sobald es initialisiert ist) Zeiger mit syntaktischem Zucker, um mir zu helfen, das "- & gt;" Zeigersyntax.
Im Allgemeinen denken Sie nicht über Referenzen nach. Sie verwenden Verweise in jeder Funktion, es sei denn, Sie benötigen eine spezifische Anforderung zum Aufrufen von Wert- oder Zeigermagie.
Referenzen sind im Wesentlichen Zeiger, die immer auf dasselbe verweisen. Eine Referenz muss nicht dereferenziert werden und kann stattdessen als normale Variable aufgerufen werden. Das ist so ziemlich alles, was da ist. Sie verwenden Zeiger, wenn Sie Zeigerarithmetik ausführen oder ändern müssen, worauf der Zeiger zeigt, und Referenzen für fast alles andere.
Verweise sind Zeigerverwerfungen mit unterschiedlicher Syntax. dh. die Referenz T & amp; ist ziemlich viel T * const wie in, der Zeiger kann nicht geändert werden. Der Inhalt von beiden ist identisch - eine Speicheradresse eines T - und beide können nicht geändert werden.
Abgesehen davon ist der einzige Unterschied die Syntax:. für Referenzen und - & gt; und * für Zeiger.
Das ist es wirklich - Referenzen sind Zeiger, nur mit unterschiedlicher Syntax (und sie sind const).
Wie wäre es mit "Zeigern, die nicht NULL sein können und nach der Initialisierung nicht geändert werden können". Auch haben sie keine Größe für sich (weil sie keine Identität von sich selbst haben).
Ich denke, Ihr geistiges Modell von Zeigern und dann eine Liste aller Randfälle, auf die Sie gestoßen sind, ist der beste Weg.
Wer keine Hinweise bekommt, wird sich viel schlechter fühlen.
Übrigens können sie NULL sein oder irgendein anderer nicht zugreifbarer Speicherplatz (es kostet nur Mühe):
%Vor%Eine Möglichkeit, darüber nachzudenken, besteht darin, einen anderen Namen für ein Objekt aus einem möglicherweise anderen Bereich zu importieren.
Zum Beispiel: Obj o; Obj& r = o;
Es gibt wirklich wenig Unterschied zwischen der Semantik von o und r.
Der wichtigste scheint zu sein, dass der Compiler den Bereich von o überwacht, um den Destruktor aufzurufen.
Wenn Sie Linux verwenden, können Sie sich Referenzen als feste Links und Zeiger als symbolische Links (symbolische Links) vorstellen. Harte Verbindung ist nur ein anderer Name für eine Datei. Die Datei wird "gelöscht", wenn alle festen Links zu dieser Datei entfernt werden.
Gleiches über Referenzen. Ersetzen Sie einfach "Hardlink" durch "Referenz" und "Datei" durch "Wert" (oder wahrscheinlich "Speicherort"?).
Eine Variable wird zerstört, wenn alle Referenzen außerhalb des Gültigkeitsbereichs liegen.
Sie können keine feste Verknüpfung zu einer nicht vorhandenen Datei erstellen. Es ist auch nicht möglich, einen Verweis auf nichts zu erstellen.
Sie können jedoch einen Symlink zu einer nicht vorhandenen Datei erstellen. Ähnlich wie ein nicht initialisierter Zeiger. Eigentlich verweisen nicht initialisierte Zeiger auf zufällige Orte (korrigiere mich, wenn ich falsch liege). Aber was ich meine ist, dass du sie nicht benutzen solltest:)
Von einem syntaktischen POV ist eine Referenz ein Alias für ein vorhandenes Objekt. Von einem semantischen POV wird eine Referenz wie ein Zeiger mit einigen Problemen (Invalidierung, Besitz usw.) entfernt und eine objektähnliche Syntax hinzugefügt. Von einem praktischen POV bevorzugen Referenzen, es sei denn, Sie müssen "kein Objekt" sagen. (Ressourcenbesitz ist kein Grund, Zeigern den Vorzug zu geben, da dies mit intelligenten Zeigern geschehen sollte.)
Update : Hier ist ein weiterer Unterschied zwischen Referenzen und Zeigern, den ich vergessen habe: Ein temporäres Objekt (ein rvalue), das an eine const-Referenz gebunden ist, hat seine Lebenszeit auf das Leben der Referenz erweitert:
%Vor% Hier ist das von der Funktion zurückgegebene Temporary an result
gebunden und hört nicht auf, am Ende des Ausdrucks zu existieren, sondern existiert bis result
stirbt. Das ist nett, denn ohne Rvalue-Referenzen und Überladen basierend auf ihnen (wie in C ++ 11), können Sie eine unnötige Kopie im obigen Beispiel loswerden.
Dies ist eine Regel, die speziell für Const-Referenzen eingeführt wurde und es gibt keine Möglichkeit, dies mit Zeigern zu erreichen.