2009-10-13 7 views
7

Ich bin verwirrt, warum der folgende C++ Code kompilieren kann. Warum erzeugt ein Aufruf zum Löschen der Methode 0 keinen Fehler ?!Delete NULL, aber keine Kompilierung Fehler

int *arr = NULL;  // or if I use 0, it's the same thing  
delete arr; 

tat ich versuche, es zu laufen, und es hat mir keine Fehler geben überhaupt ...

+4

Der Code kompiliert nicht - Sie benötigen einen Typ für den Zeiger (z. B. void) und nicht nur ein Qualifikationsmerkmal; das ist nicht (alt) C. –

Antwort

19

Die Sprache C++ garantiert, dass p löschen wird nichts tun, wenn p gleich NULL ist.

Für weitere Informationen Besuche Abschnitt 16.8,9 here:

+0

Noch war die Frage, warum der Code * kompiliert *; nicht warum gibt es keinen Laufzeitfehler. – Josh

+5

In C++ ist es legal, einen NULL-Zeiger zu löschen, daher ist der Compiler damit einverstanden. –

+0

Ist es erlaubt Null zu dereferenzieren? Wie wäre es mit dem Überlaufen des Stapels? Zeigen Sie mir einen Compiler, der diese Bedingungen ausschließt ... – Josh

0

NULL und 0 sind nicht das Gleiche. In C++ sollten Sie 0 verwenden.

Es gibt nichts, was syntaktisch falsch oder mehrdeutig beim Löschen des Null-Zeigers ist. In der Tat ist dies per definitionem ein No-Op; das heißt, die Operation des Löschens der 0. Adresse ist äquivalent dazu, überhaupt nichts zu tun.

+6

Eigentlich ist in C++ NULL als 0 definiert. Außerdem ist NULL vs. 0 eine stilistische Debatte, für die es keine eindeutige Antwort gibt. – rlbond

+2

Es gibt absolut keinen Grund, 0 in C++ vor NULL zu bevorzugen. Obwohl aus irgendeinem Grund die Empfehlung, "0 in C++" zu verwenden, von Zeit zu Zeit hier und da auftaucht. Ich weiß nicht, woher diese urbanische Legende stammt, aber auch hier ist absolut nichts an der Verwendung von NULL in C++ zu ändern und NULL ist aus Gründen der besseren Lesbarkeit besser als 0. – AnT

+1

Stroustrup bevorzugt 0 statt NULL: http : //www.research.att.com/~bs/bs_faq2.html # null – ChrisW

0

Obwohl Ihr Beispiel trivial ist, gibt es keine Möglichkeit für einen Compiler, den Wert eines Zeigers (zur Kompilierzeit) zu kennen.

Sie können auch dereferenzieren null bei der Kompilierung:

// this code compiles 
Object* pObject = 0; 
pObject->SomeMethod(); 

Compiler sind nicht diese Art von Fehlerbedingungen bei der Kompilierung zu handhaben gebaut.

Und die meisten (alle?) Implementierungen haben 'delete 0' als Nicht-Operation. Dieser Code sollte gut laufen:

Object* pObject = new Object(); 
delete pObject; 
pObject = 0; 
delete pObject; 

Obwohl ich auf, dass nicht zu 100% bin sicher :)

+3

Ich glaube nicht, Löschen von null ist ein Laufzeitfehler. – Jacob

+0

Sie haben Recht. Ich habe Probleme mit der doppelten Löschung, aber ... oder vielleicht stelle ich mir Dinge vor? – Josh

+4

Jeder C++ - Compiler, der "delete NULL" als etwas anderes als ein No-Op behandelt, ist ein fehlerhafter Compiler. Die Sprache C++ gibt an, dass das Löschen eines Nullzeigers sicher ist. (Wenn Sie zweimal auf denselben Non-NULL-Pointer klicken, werden Sie in Schwierigkeiten geraten) –

1

Sie einen NULL-Zeiger problemlos löschen können, und der Fehler nicht bei der Kompilierung zur Laufzeit haben kann/können, aber sein wird.

int *ptr_A = &a; 
ptr_A = NULL; 
delete ptr_A; 

Normalerweise ist es bequem zu tun:

... 
delete ptr; 
ptr = NULL; 
+1

Es ist normalerweise eine schlechte Übung, einen Zeiger zu NULLEN. Der Grund ist, dass Zeiger in Klassen gekapselt werden sollten. 'delete' tritt dann in Destruktoren auf, nach denen der Zeiger nicht mehr existiert oder in der Zuweisung, in der der Zeiger einen neuen Wert bekommt. Daher gibt es normalerweise keine Methoden, die den Zeiger auf NULL setzen würden. Die eine offensichtliche Ausnahme ist ein "optionaler" Teil eines Objekts, das nicht mehr benötigt wird, aber man beachte 'boost :: optional ' dafür. – MSalters

1

Es ist ein de-facto-Standard in C und C++ Sprachen (und nicht nur in ihnen), dass Ressource Deallokation Routinen müssen Null-Pointer-Argumente akzeptieren und mach einfach nichts. Eigentlich ist es eine eher konvenierende Konvention. Also, die wirkliche Frage hier: Warum überrascht es Sie? Was lässt Sie glauben, dass ein Fehler auftreten sollte? Außerdem, was macht Sie denken, dass es auf kompilieren sollte ???

BTW, Ihre Frage, die Art, wie es gesagt wird, scheint nicht viel Sinn zu machen, da Ihr Code tatsächlich nicht kompilieren kann. Der angeblichen Zeigerdeklaration fehlt ein Typ, der jeden Compiler dazu veranlasst, eine Diagnosemeldung auszugeben.

+3

s/de-facto/de jure/- siehe Zitat aus der ISO-Norm. – MSalters

Verwandte Themen