wake-up-neo.com

Kann ich if (Zeiger) anstelle von if (Zeiger! = NULL) verwenden?

Ist es sicher, einen Zeiger darauf zu prüfen, dass er nicht NULL ist, indem er einfach if(pointer) schreibt oder muss ich if(pointer != NULL) verwenden?

154
danijar

Sie können; Der Nullzeiger wird implizit in boolesches false konvertiert, während Nicht-Nullzeiger in true konvertiert werden. Aus dem C++ 11-Standard Abschnitt über Boolesche Konvertierungen:

Ein prvalue aus arithmetischer, nicht begrenzter Aufzählung, einem Zeiger oder einem Zeiger auf einen Mitgliedstyp kann in eine .__-Datei umgewandelt werden. prvalue vom Typ bool. Ein Nullwert, ein Nullzeigerwert oder ein Nullelementzeigerwert wird in .__ konvertiert. false; Jeder andere Wert wird in .__ konvertiert. true . Ein prvalue vom Typ std::nullptr_t kann in einen prvalue von .__ umgewandelt werden. Art bool ; Der resultierende Wert ist false .

171
Joni

Ja du könntest.

  • Ein Nullzeiger wird implizit in false konvertiert
  • ein nicht-null-Zeiger wird in true konvertiert.

Dies ist Teil der C++ - Standardkonvertierung, die in die Klausel Boolean conversion fällt:

§ 4.12 Boolesche Konvertierungen

Ein prvalue aus arithmetischer, nicht begrenzter Enumeration, pointer oder einem Zeiger auf einen Member-Typ kann in einen prvalue vom Typ bool umgewandelt werden. Ein Nullwert, Nullzeigerwert oder Nullelementzeigerwert wird in false konvertiert. Jeder andere Wert wird in true konvertiert. Ein prvalue vom Typ std :: nullptr_t kann in einen prvalue vom Typ bool umgewandelt werden. Der resultierende Wert ist falsch.

35
billz

Ja, du kannst. Ich bevorzuge die Verwendung von if(pointer), weil es einfacher ist, zu lesen und zu schreiben, wenn Sie sich erst einmal daran gewöhnt haben.

Beachten Sie auch, dass C++ 11 nullptr eingeführt hat, das gegenüber NULL bevorzugt wird.

29
Yu Hao

Die Frage ist beantwortet, aber ich möchte meine Punkte hinzufügen. 

Ich werde immer if(pointer) anstelle von if(pointer != NULL) und if(!pointer) anstelle von if(pointer == NULL) vorziehen: 

  • Es ist einfach, klein 
  • Weniger Chancen, einen fehlerhaften Code zu schreiben, angenommen, der Operator == mit = ist falsch geschrieben.
    if(pointer == NULL) kann falsch geschrieben werden if(pointer = NULL) Also werde ich es vermeiden, am besten ist es nur if(pointer).
    (Ich habe auch eine Yoda-Bedingung in einer Antwort vorgeschlagen , aber das ist eine andere Sache.)

  • In ähnlicher Weise schreibe ich für while (node != NULL && node->data == key) einfach while (node && node->data == key), die für mich offensichtlicher ist (zeigt die Verwendung eines Kurzschlusses).

  • (kann ein dummer Grund sein) Da NULL ein Makro ist, nehmen wir an, jemand würde sich versehentlich mit einem anderen Wert neu definieren.
11
Grijesh Chauhan

Die explizite Suche nach NULL könnte dem Compiler einen Hinweis auf das geben, was Sie versuchen, was dazu führt, dass er weniger fehleranfällig wird.

 enter image description here

9
Minqi Pan

Ja, du kannst. Die Möglichkeit, Werte mit Nullen implizit zu vergleichen, wurde von C geerbt und ist in allen Versionen von C++ vorhanden. Sie können auch if (!pointer) verwenden, um Zeiger auf NULL zu überprüfen.

8
dasblinkenlight

Die relevanten Anwendungsfälle für Nullzeiger sind

  • Umleitung zu etwas wie einem tieferen Baumknoten, der möglicherweise nicht existiert oder noch nicht verlinkt wurde. Das ist etwas, was Sie immer in einer dedizierten Klasse eng zusammenhalten sollten, daher ist Lesbarkeit oder Prägnanz hier kein Thema.
  • Dynamische Besetzungen Das Umwandeln eines Basisklassenzeigers auf eine bestimmte abgeleitete Klasse (etwas, das Sie erneut vermeiden sollten, aber manchmal als notwendig erachten) ist immer erfolgreich, führt jedoch zu einem Nullzeiger, wenn die abgeleitete Klasse nicht übereinstimmt. Eine Möglichkeit dies zu überprüfen ist

    Derived* derived_ptr = dynamic_cast<Derived*>(base_ptr);
    if(derived_ptr != nullptr) { ... }
    

    (oder vorzugsweise auto derived_ptr = ...). Dies ist nun schlecht, da der abgeleitete (möglicherweise ungültige, d. H. Null) Zeiger außerhalb des Bereichs des Sicherheitsüberwachungs-if-Blocks verbleibt. Dies ist nicht erforderlich, da Sie in C++ boolesche konvertierbare Variablen einfügen können innerhalb einer if- Bedingung :

    if(auto derived_ptr = dynamic_cast<Derived*>(base_ptr)) { ... }
    

    was nicht nur kürzer und sicherer ist, sondern auch viel klarer ist: Wenn Sie in einer separaten if-Bedingung nach null suchen, fragt sich der Leser "ok", daher muss derived_ptr hier nicht null sein ... nun, warum wäre es null? " Während die einzeilige Version sehr deutlich sagt: "Wenn Sie base_ptr sicher in Derived* umwandeln können, verwenden Sie es für ...".

    Das Gleiche funktioniert genauso gut für alle anderen möglichen Fehleroperationen, die einen Zeiger zurückgeben, obwohl IMO dies generell vermeiden sollte: Es ist besser, etwas wie boost::optional als "Container" für die Ergebnisse möglicherweise fehlerhafter Operationen anstelle von Zeigern zu verwenden.

Wenn also der Hauptanwendungsfall für Nullzeiger immer in einer Variation des impliziten Cast-Stils geschrieben werden sollte, würde ich sagen, dass es aus Gründen der Konsistenz gut ist, immer diesen Stil zu verwenden, dh ich würde dafür plädieren if(ptr) über if(ptr!=nullptr).


Ich fürchte, ich muss mit einer Anzeige enden: Die if(auto bla = ...)-Syntax ist eigentlich nur eine etwas umständliche Annäherung an die real - Lösung für solche Probleme: Mustervergleich . Warum sollten Sie zuerst eine Aktion erzwingen (z. B. einen Zeiger werfen) und dann in Betracht ziehen, dass ein Fehler auftreten könnte ... Ich meine, es ist lächerlich, nicht wahr? Es ist so, als hätten Sie etwas zu essen und möchten Suppe machen. Sie geben es Ihrem Assistenten mit der Aufgabe, den Saft zu extrahieren, wenn es sich um ein weiches Gemüse handelt. Du siehst es nicht zuerst an. Wenn Sie eine Kartoffel haben, geben Sie sie immer noch Ihrem Assistenten, aber sie schlagen sie mit einem Fehlerhinweis in Ihr Gesicht. Ah, zwingende Programmierung!

Viel besser: Betrachten Sie sofort alle Fälle, auf die Sie stoßen könnten. Dann handeln Sie entsprechend. Haskell:

makeSoupOf :: Foodstuff -> Liquid
makeSoupOf [email protected](Potato{..}) = mash (boil p) <> water
makeSoupOf vegetable
 | isSoft vegetable  = squeeze vegetable <> salt
makeSoupOf stuff  = boil (throwIn (water<>salt) stuff)

Haskell hat auch spezielle Werkzeuge für den Fall, dass eine ernsthafte Möglichkeit zum Scheitern besteht (sowie für eine ganze Reihe anderer Dinge): Monaden. Dies ist jedoch nicht der Ort, um diese zu erklären.

⟨/Inserat⟩

2
leftaroundabout

Ja. Eigentlich sollten Sie. Wenn Sie sich fragen, ob ein Segmentierungsfehler erstellt wird, ist dies nicht der Fall.

0
darshandzend

ja bitte! In der Tat ist das Schreiben von if (Zeiger) eine bequemere Schreibweise als wenn (Zeiger! = NULL), weil es ist leicht zu debuggen. 2. leicht verständlich 3. Wenn versehentlich der Wert von NULL definiert wird, stürzt auch der Code nicht ab

0
Palak Jain