2010-11-24 26 views
7

Lets sagen Sie so etwas wie dieses:Nach einer Nullreferenz suchen?

int& refint; 
int* foo =0; 
refint = *foo; 

Wie können Sie überprüfen, ob die Referenz NULL ist ein Absturz zu vermeiden?

+7

Sie den Entwickler ziehen, wer das in einen dunklen Raum schrieb mit einem Stuhl und ein Licht auf sie scheint. Dann verbrennst du sie mit Zigaretten, bis sie bereuen. –

Antwort

11

Sie können eine Referenz nicht so spät initialisieren. Es muss initialisiert werden, wenn es erklärt wird.

On Visual C++ ich

Fehler C2530: 'REFINT': Referenzen muss

mit Ihrem Code initialisiert werden.

Wenn Sie den Code "reparieren", tritt der Absturz (streng undefiniertes Verhalten) zur Referenznutzungszeit in VC++ v10 auf.

Um dies sicher zu machen, überprüfen Sie den Zeiger bei der Referenzinitialisierung oder der Zuweisungszeit.

int* foo =0; 
if (foo) 
{ 
    int& refint(*foo); 
    int i(refint); 
} 

aber, dass noch nicht foo Punkte zu nutzbaren Speichern garantiert, noch dass es so bleibt, während die Referenz im Gültigkeitsbereich befindet.

+0

"der Absturz wird zur Referenzinitialisierungszeit passieren" - Versprechen? ;-) –

+0

Der Absturz muss nicht (und oft nicht) zur Referenzinitialisierungszeit geschehen. mit UB konnte alles passieren, auch kein Absturz. –

+0

@Charles, überprüft meine Annahmen im Debugger und bearbeitet. Es stürzt nur in VC++ ab, wenn ich die Referenz verwende. UB allround ... –

5

Sie haben nicht, wenn Sie eine "Null" -Referenz haben, haben Sie bereits undefiniertes Verhalten. Sie sollten immer überprüfen, ob ein Zeiger Null ist, bevor Sie versuchen, durch Dereferenzieren des Zeigers eine Referenz zu bilden.

(Ihr Code ist illegal, Sie eine nicht initialisierte Referenz nicht erstellen und versuchen, es zu binden, indem es die Zuweisung; Sie es nur bei der Initialisierung binden können.)

4

Im Allgemeinen kann man nicht.

Wer "NULL-Referenz erstellt" (oder versucht, sollte ich sagen) hat bereits undefiniertes Verhalten aufgerufen, so dass der Code abstürzen könnte (oder auch nicht), bevor Sie die Möglichkeit haben, etwas zu überprüfen.

Wer die Referenz erstellt sollte getan haben:

int *foo = 0; 
if (foo) { 
    int &refint = *foo; 
    ... use refint for something ... 
} 

Normalerweise Problem des Anrufers es angesehen, wenn sie *foo geschrieben haben, wenn foo ist null, und es ist nicht eine Verantwortung der Funktion für diese Art von Fehlern zu überprüfen in der Code anderer Funktionen. Aber Sie könnten Dinge wie assert(&refint); durch Ihren Code werfen. Sie könnten helfen, Fehler zu erkennen, die von Ihren Anrufern gemacht wurden, denn schließlich gibt es für jede Funktion, die Sie schreiben, eine vernünftige Chance, dass der Anrufer Sie selbst ist.

-5

Sie müssen nicht, Referenzen können nicht null sein.

Lesen Sie das Handbuch.

0

Um den obigen Code Kompilierung zu machen, werden Sie um den Auftrag zu wechseln haben:

int* foo =0; 
int& refint = *foo; // on actual PCs, this code will crash here 

(Es älteren Prozessor oder Laufzeitarchitekturen sein kann, wo dies funktioniert.)

0

....alle der oben genannten sagen, wenn Sie einen NULL-Verweis haben tun möchten, verwenden Sie boost::optional<>, wirkt wie ein Zauber ..

1

die Antworten oben sind alle richtig, aber wenn Sie aus irgendeinem Grund dachte, das ich tun möchte, mindestens eine Person sollte eine Antwort geben. Ich versuche gerade, eine schlechte Referenz in irgendeinem Quellcode aufzuspüren, und es wäre nützlich zu sehen, ob jemand diese Referenz gelöscht und sie irgendwann auf null gesetzt hat. Hoffentlich wird dies nicht zu vielen Downstimmen führen.

#include <iostream> 
    int main() 
    { 
     int* foo = nullptr; 
     int& refint = *foo; 

     if(&refint == nullptr) 
      std::cout << "Null" << std::endl; 
     else 
      std::cout << "Value " << refint << std::endl; 
    } 

Ausgang:

Null

+0

Hinweis: Ausgabe ist in diesem Fall Null, weil int * foo; war einfach nur nullptr. Da es nicht initialisiert ist, könnte es alles sein. Ich würde es auf nullptr initialisieren. –

+0

@LennartRolland Guter Punkt, behoben. – marsh