Frage

Das kam als einer der Code-Review-Kommentare auf.

Ist es eine gute Idee für NULL zu überprüfen, bevor für jedes Objekt löscht Aufruf?

Ich verstehe intern delete-Operator prüft, ob NULL und ist überflüssig, aber das Argument streckte war delete als Betreiber überlastet werden kann und wenn die überladene Version für die NULL überprüft nicht, kann es zum Absturz bringen. So ist es sicher und vernünftig anzunehmen, dass, falls und wenn löschen wird es für die NULL oder nicht, wird überlastet werden? In meiner billigen Verständnis den ersten Fall anzunehmen, dass Löschüberlastet wird Pflege der NULL-Prüfung nehmen, und die Überprüfung Punkt nicht hält gut. Was denken Sie?

War es hilfreich?

Lösung

Nein, nicht überprüfen, für null. Die Norm sagt, dass delete (T*)0; gültig ist. Es wird nur der Code für keine Vorteile erschweren. Wenn operator delete überlastet ist, es ist besser für null bei der Umsetzung des Betreibers zu prüfen. Nur speichert Codezeilen und Bugs.

EDIT: Diese Antwort akzeptiert wurde und upvoted, doch meiner Meinung nach, es war nicht sehr informativ. Es gibt ein fehlendes Stück in allen Antworten hier, und um das Gewissen willen, lassen Sie mich hier, um dieses letzte Stück hinzufügen.

Die Norm sagt eigentlich in [basic.stc.dynamic], zumindest seit dem C ++ 03:

  

Jede Verteilung und / oder Aufhebung der Zuordnung definierten Funktionen in einem C ++ Programm, einschließlich den Standardversionen in der Bibliothek, gelten die Semantik entsprechen angegeben in 3.7.4.1 und 3.7.4.2.

Wenn die referenzierten Abschnitte, sowie einige andere Plätze in der Standard in anderen Antworten aufgelistet, sagen, dass die Semantik des Leitens eines Null-Zeiger sind ein No-op.

Andere Tipps

Ich würde sagen, das ist mehr ein Grund, um sicherzustellen, wenn Sie operator delete überlasten, dann sollten Sie immer es für NULL überprüfen, sonst sind Sie die Semantik zu brechen.

  

Ist es eine gute Idee für NULL zu überprüfen, bevor für jedes Objekt löscht Aufruf?

Nein!

int *p = NULL;
delete p ; //no effect

Die Norm sagt [Abschnitt 5.3.5 / 2]

  

Wenn der Operand ein Klassentyp hat, wird der Operand auf einen Zeigertyp umgewandelt, indem die oben erwähnte Umwandlungsfunktion aufrufen, und das umgewandelte Operand wird an Stelle des ursprünglichen Operanden für den Rest dieses Abschnitts verwendet. In beiden alternativen, , wenn der Wert des Operanden der Lösch- ist der Null-Zeiger der Betrieb keine Wirkung .

Darüber hinaus in Abschnitt 18.4.1.1/13

void operator delete(void* ptr) throw();

void operator delete(void* ptr, const std::nothrow_t&) throw();

  

Standardverhalten:

     

-. Für einen Nullwert von ptr, nichts tun

     

- Jeder anderer Wert von ptr wird ein Wert zurückgegeben wird zuvor von einem Aufruf den Standardoperator neu, die nicht durch einen dazwischenliegenden Aufruf Operator delete (void *) (17.4.3.7) für ungültig erklärt wurde. Für eine solche Nicht-Null-Wert von ptr, reklamiert Lagerung durch den früheren Aufruf der Standardoperator zugewiesen neu.

Bearbeiten :

James Kanze hier sagt dass

  

Es ist immer noch die responisiblity des Betreibers löschen (oder löschen []) zu überprüfen; der Standard garantiert nicht, dass es nicht einen Null-Zeiger gegeben wird; der Standard verlangt, dass es sich um eine no-op, wenn ein Null-Zeiger angegeben. Oder, dass die Umsetzung darf es nennen. Nach dem jüngsten Entwurf: „Der Wert des ersten zu einer Freigabe-Funktion geliefert Arguments kann einen Null-Zeiger-Wert sein, und wenn ja, und wenn die Freigabe-Funktion ein in der Standardbibliothek versorgt wird, hat der Aufruf keine Wirkung.“ Ich bin mir nicht ganz sicher, was die Auswirkungen, dass „man in der Standardbibliothek versorgt ist“ soll --- genommen wird buchstäblich, da seine Funktion nicht ist von der Standardbibliothek zur Verfügung gestellt, würde der Satz offenbar nicht anzuwenden . Aber irgendwie, das macht keinen Sinn.

Ich würde sagen, dass es in der Verantwortung einer überladenen delete ist zu verhalten, wie Sie delete zu verhalten erwarten. Das heißt, es sollte handle NULL-Zeiger als no-op.

Und so, wenn ein überlasteter löschen Aufruf, sollten Sie nicht für NULL überprüfen. Sie sollten auf der überlasteten löschen verlassen korrekt umgesetzt werden.

Kein Bedarf null zu überprüfen. delete-Operator tut Check für null so zusätzliche Prüfung nicht erforderlich ist.

delete (T*)0; gültig ist und tut nichts, ähnlich free(NULL); auch gültig ist, und tut nichts. Wenn Sie den delete Betreiber überlasten, sollten Sie Ihre Implementierung die gleiche Semantik tragen. Die Norm sagt, wie der Standard-delete funktionieren wird, aber ich glaube nicht, es sagt, wie ein überlasteter delete verhalten soll. Aus Gründen der Kohärenz mit dem Standard / Standardverhalten, sollte es (T*)0 als Eingabe ermöglichen.

Von Standard-docs, 18.5.1.1.13 unter delete,

  

Standardverhalten: Wenn ptr null ist, tut nichts Ansonsten die Lagerung durch den früheren Aufruf zugewiesen reklamiert zu.   Betreiber neu.

Also, Sie müssen nicht überprüfen standardmäßig ..

Keine Notwendigkeit für NULL zu prüfen, vor dem Löschen. Wenn jemand delete mit etwas Überlastung, die in üblichen Weise verhält sie nicht dann , dass die das eigentliche Problem. Niemand sollte die leichte Schulter nehmen die Aufgabe delete von Überlastung und sollte immer das erwartete Verhalten unterstützen wie für NULL Kontrolle und keine Maßnahmen.

Doch für was es wert ist, sollten Sie immer denken Sie daran, jeden Zeiger zuweisen Null, dass Sie gerade gelöscht haben, es sei denn, zum Beispiel sind Sie über den Zeiger löschen als auch:

void MyObj::reset()
{
    delete impl_;
    impl_ = 0;    // Needed here - impl_ may be reused / referenced.
}

MyObj::~MyObj()
{
    delete impl_; // No need to assign here as impl_ is going out of scope.
}

Ist es nicht notwendig zu überprüfen. Wenn jemand die Methode überlasten, ist seine Verantwortung zu, was auch immer mit NULL.

Ich würde sagen, die Fragen unvollständige Informationen enthalten. Mein Geschäft hat noch einen Scheck für NULL vor Löschen in unserem Codierungsstandard, wie wir noch einen Compiler / Plattform-Konfiguration haben, dass wir das geht in undefiniertes Verhalten mit dem defualt delete-Operator unterstützen müssen, wenn es NULL übergeben wird. Wenn das ursprüngliche Plakat, das eine simular Situation hat, dann gibt es einen Punkt, um die Prüfung auf NULL, andernfalls ändern Sie den Codierungsstandard!

Ein bisschen von C ++ Pedanterie: NULL ist kein Einbau-Konzept. Ja, wir alle wissen, was es bedeutet, aber in C ++ vor C ++ 0X das Null-Zeiger-Konzept ist einfach der Wert 0 NULL ist in der Regel eine plattformspezifische Makro, dass expandiert auf 0.

Mit C ++ 0X wir bekommen nullptr, die klarer als eine reine Null ist und nicht konvertierbar einen integraler Typen mit Ausnahme Bool, und ist ein besserer Begriff als NULL (oder vielleicht eine bessere Umsetzung des Konzepts hinter NULL) .

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top