Warum gibt es in C ++ keine "NULL-Referenz"?

8

Ich habe die C ++ - FAQ gelesen - " 8.6 - Wann sollte ich Referenzen verwenden und Wann sollte ich Zeiger verwenden? "und insbesondere diese Aussage:

  

Verwenden Sie Referenzen, wenn Sie können, und Zeiger, wenn Sie müssen.

     

...

     

Die Ausnahme von dem obigen ist, wo der Parameter oder der Rückgabewert einer Funktion eine "Sentinel" -Referenz benötigt - eine Referenz, die sich nicht auf ein Objekt bezieht. Dies wird normalerweise am besten erreicht, indem ein Zeiger zurückgegeben / aufgenommen wird und dem NULL-Zeiger diese besondere Bedeutung gegeben wird (Referenzen müssen immer Alias-Objekte sein, nicht ein dereferenzierter NULL-Zeiger).

Nach dem, was ich gesehen habe, ist die Notwendigkeit einer "Sentinel" -Referenz in der Tat oft der Grund, Zeiger anstelle von Referenzen zu verwenden. Was ich mich frage ist: Warum hat C ++ keinen speziellen "NULL-Wert" für Referenzen? Es scheint, dass es Zeiger fast unnötig machen würde, was viele Probleme lösen würde.

Warum war das nicht Teil der Sprachspezifikation?

Bearbeiten:

Ich bin mir nicht sicher, ob meine Frage klar ist - ich denke, ich frage nicht im Geringsten nach NULL-Referenzen. Meistens habe ich gelesen, dass in C ++ "die Referenz das Objekt ist". Und in den meisten OOP-Sprachen können Objekte NULL sein - Pascal, C #, Java, JavaScript, PHP usw. In all diesen Fällen können Sie someObject = null oder someObject := nil verwenden. Tatsächlich unterstützt Pascal auch Zeiger, erlaubt aber trotzdem Objekten nil zu sein, da sie verwendet werden. Warum ist C ++ irgendwie speziell und hat kein NULL-Objekt? War es nur ein Überblick oder eine wirkliche Entscheidung?

    
this.lau_ 10.07.2012, 07:49
quelle

5 Antworten

13

Weil eine Referenz die Semantik trägt, dass sie auf eine gültige Speicheradresse zeigt, die sich niemals ändert; d.h., dass die Dereferenzierung sicher / definiert ist und daher keine NULL-Prüfungen erforderlich sind. Referenzen können nicht vom Design neu zugewiesen werden.

Sie verwenden einen Zeiger, wenn die Variable NULL sein kann und Client-Code diesen Fall behandeln muss. Sie verwenden eine Referenz, wenn Sie eine gültige / initialisierte Speicheradresse garantieren können.

Ein Beispiel für die Verwendung von Zeigern besteht darin, als Mitglied einer Klasse eine "Referenz" zu einer Instanz zu speichern, die zum Zeitpunkt der Klassenbildung möglicherweise nicht bekannt ist oder nicht initialisiert werden kann. Mitgliederreferenzen müssen jedoch zur Erstellungszeit (über Initialisierungslisten) initialisiert werden und ihre Zuweisung kann nicht zurückgestellt werden.

Wenn Sie eine NULL-Referenz zulassen, unterscheidet sie sich dann nicht von einem Zeiger neben der Syntax (die gleichen NULL-Checks müssten stattfinden).

Aktualisierung:

  

"Und in den meisten OOP-Sprachen können Objekte NULL sein - Pascal, C #, Java, JavaScript, PHP usw. [...] Also warum ist C ++ irgendwie speziell und hat kein NULL-Objekt? War es nur ein Überblick oder eine tatsächliche Entscheidung? "

Ich denke, Sie sind ein bisschen verwirrt darüber. Java und C # usw. könnten den Eindruck von "NULL-Objekten" erwecken, aber diese Objektreferenzen ähneln mehr oder weniger einem C ++ - Zeiger mit einfacherer Syntax, GC-Instrumentierung und Exception-Throwing. Wenn Sie in diesen Sprachen mit einem "Null-Objekt" arbeiten, erhalten Sie eine Art Ausnahme wie NullReferenceException (C #). Hölle, in Java heißt es eine NullPointerException .

Sie müssen nach null suchen, bevor Sie sie sicher verwenden können. Ähnlich wie C ++ - Zeiger (mit Ausnahme der meisten verwalteten Sprachen werden Zeiger standardmäßig auf NULL initialisiert, während Sie in C ++ normalerweise dafür sorgen, dass der ursprüngliche Zeigerwert eingestellt wird (andernfalls undefined / welcher Speicher bereits vorhanden war).) / p>

In der C ++ - Ansicht geht es um eine Auswahl und damit um eine ausführliche Beschreibung:

  • Verwenden Sie einen einfachen Zeiger, um zu tun, wie es Ihnen gefällt, und überprüfen Sie gegebenenfalls NULL.
  • Verwenden Sie Referenzen, die eine Compiler-erzwungene Validitätssemantik / -beschränkung haben.
  • Rollen Sie Ihre eigenen Smart-Pointer, die Buchhaltung machen und sich so verhalten, wie Sie es wollen.
  • Leere Zeiger verwenden (vorsichtig!), um einen nicht typisierten Speicherblock zu referenzieren, falls dies erforderlich ist.
Preet Kukreti 10.07.2012, 07:55
quelle
6

Bitte werfen Sie einen Blick auf Unterschiede zwischen Zeigern und Referenzen - während der Standard offen lässt, wie Referenzen implementiert werden, werden sie im Moment immer als Zeiger implementiert.

Was bedeutet, dass der Hauptunterschied zwischen ihnen a) Semantik b) Zeiger kann wieder eingefügt werden c) Zeiger können null sein.

Die kurze Antwort ist also, dass dies mit Absicht gemacht wurde. Wenn Sie als Programmierer eine Referenz sehen, sollten Sie wissen, dass a) diese Referenz gefüllt ist, b) sie sich nicht ändert (und c) Sie sie mit derselben Semantik wie ein Objekt verwenden können).

Würde der Standard eine Nullreferenz zulassen, müssten Sie immer auf Null überprüfen, bevor Sie eine Referenz verwenden, die nicht erwünscht war.

Bearbeiten:

Was die Bearbeitung betrifft, so könnte die Verwirrung hier vielleicht auf die Tatsache zurückzuführen sein, dass die meisten einfacheren OO-Sprachen verbergen, was vor sich geht. Um Java als Beispiel zu nehmen, während es aussieht, als ob Sie NULL-Objekte haben und diese zuweisen können, können Sie wirklich nicht - was wirklich vor sich geht ist, dass Java nur Zeiger hat und diesen Zeigern Nullwerte zuweisen kann. Da es unmöglich ist, Objekte direkt in Java zu haben, verzichten sie auf die Pointer-Semantik und behandeln den Zeiger als Objekt. C ++ ist einfach mächtiger - und fehleranfällig (Java-Enthusiasten würden sagen, dass Stack-Benutzerklasseninstanzen nicht erforderlich sind, und die Entscheidung, sie nicht in Java zu haben, wurde entwickelt, um die Komplexität zu reduzieren und Java benutzerfreundlicher zu machen). Da Java keine Objekte besitzt, enthält es auch keine Referenzen. Was wirklich nicht hilft, ist, dass Java aufruft, was eine C ++ Person einen Pass-by-Wert eines Zeigers Pass-by-Reference nennen würde.

    
Cookie 10.07.2012 07:58
quelle
1

Eine C ++ - Referenz ist keine Referenz in dem Sinne, dass die meisten anderen Sprachen diesen Begriff verwenden; Es ist mehr wie ein Alias ​​. Wenn Sie eine C ++ - Referenz verwenden, wird die Dereferenzierung eines Zeigers nicht wie bei der Dereferenzierung ausgeführt. es ist effektiv ist das ihm zugewiesene Objekt.

Es gibt nicht wirklich so etwas wie eine null-Objekt -Instanz , so dass Sie keine C ++ - Referenz auf so etwas erstellen können. In anderen Sprachen entspricht eine Nullreferenz dem C ++ - Nullzeiger. Es enthält eigentlich nichts.

Nun zu deinen anderen Gedanken: 1. unnachvollziehbare Referenzen zu haben ist meiner Meinung nach eine gute Sache; es bedeutet, dass Sie alle Vorteile der Weitergabe als Referenz erhalten, ohne die Anforderung, überall auf Nullen zu prüfen. 2. Nullable-Referenzen ersetzen keine Zeiger ... Wenn Sie Speicher- oder IO-Arbeit auf einer niedrigen Ebene durchführen müssen, werden Sie einen rohen Zugriff auf Speicher- und Speicherkarten-Geräte benötigen. Sie können sich C # (oder C ++ / CLR) ansehen, die aus genau diesem Grund Verweise und nicht verwaltete Zeiger verwaltet hat.

    
Rook 10.07.2012 10:14
quelle
1

Der Verweis per Definition sollte mit einer anderen Variablen oder einem anderen Objekt verknüpft sein. Also verletzt eine leere oder Null-Referenzart ihren Existenzzweck.

Technisch bedeutet das, dass Sie mit einer Nullreferenz beginnen, dann eine Variable zuweisen oder sie einer anderen Variablen zuweisen. Dies ist einfach NICHT, was Referenz für geschaffen werden sollte.

Es gibt verschiedene andere Verwendungen von Zeigern, die Referenz einfach nicht replizieren kann. B. auf einen großen Teil komplexer Daten (eine Folge von Bytes) mit einer kleinen Menge Speicher unter Verwendung eines Zeigers Bezug nehmen und diesen so oft wie nötig weitergeben, indem nur 8 Bytes für den Zeiger ausgegeben werden. Sie können das nicht mit einer Referenz tun, ohne den gleichen Speicher zu verschwenden.

Die Referenz wäre immer an einen Typ gebunden, was beim Zeiger nicht der Fall ist.

    
fayyazkl 10.07.2012 07:58
quelle
0

Die Referenz muss sich auf etwas beziehen, daher ist die Nullreferenz nicht verfügbar.
C hat keine Referenzen und wir können nur Zeiger in dieser Sprache verwenden, also ist dies eine Kompatibilität mit der C-Sprache

    
ForEveR 10.07.2012 07:55
quelle