Stilfrage: if (ptr) oder if(ptr != NULL)
-
Nexus schrieb:
Welche der beiden Möglichkeiten verwendet ihr zum Abfragen, ob ein Zeiger auf Null zeigt?
So gefragt 2).

Mit 1) schaue ich, ob der Zeiger gültig oder ungültig ist, ob er auf etwas zeigt oder auf nix. Ob es den pointee gibt oder nicht. Ob der Auftrag noch zu erledigen ist oder schon weg. Und so weiter.
Mit 2) schaue ich, ob der Zeiger auf *NULL zeigt. Also in Bäumen, verketteten Listen und so, wo in der Doku explitzit steht, daß NULL das Ende anzeigt.
Wobei ich aber nie NULL nehme, sondern nur 0 und bald nullptr.
Demnach müßte der SmartPointer für mich 1) anbieten und sonst nichts. Ich würde nie einen Smartpointer mit 0 initialisieren oder ihm eine 0 zuweisen, warum sollte ich dann so ulkig sein, und schauen, ob eine 0 drin ist?
IsNull ist nur eine Verblümung von 2), das müßte IsValid oder so heißen, um zur Verblümung von 1) zu werden.
Ich bin auch gegen Umdrehen wie bei if(0==ptr), weil das zu untersuchende Objekt ganz links beim Lesen hilft, so wie das empfangende Objekt in Zuweisungen ganz links, zum Beispiel if(0<=auszahlung-kontostand) versus if(auszahlung>=kontostand). Den extrem seltenen Zuweisungsfehler da wegzumachen, indem man mit so einem großen Hammer draufhaut und den Lesefluß==Debugfluß signifikant stört, ist nicht mehr gerechtfertigt.
Übrigens ist SafeBool auch eine Operation gegen ein Problem, das ich nicht habe. Ich bräuchte also kein SafeBool, da täte es vielleicht schon auch ein bool oder besser ein void*. Aber Einbasteln schadet erst recht nicht, weil ich von den SafeBool-Problemchen wohl auch nicht erwischt werden würde.
-
Nexus schrieb:
drakon schrieb:
Naja. Das ist ja nicht die Welt eine weitere Funktion zu haben. Im Gegenzug machst du aber alle glücklich.

Vor allem bei Operatoren finde ich das sowieso durchaus legitim eine benannte Version der Funktion zu haben.Das erinnert mich an einen Thread aus dem SFML-Forum, wo tatsächlich vorgeschlagen wurde, für alle möglichen Funktionen Aliase einzuführen, um zusätzlich eine andere Namenskonvention zu haben.

Für x-beliebige Funktionen sicher nicht! Obwohl.. richtig sinnvoll wäre natürlich, wenn man die STL für alle schön macht:
std::remove_if (..); std::RemoveIf (..);Das wäre doch schon was tolles! :p (Mist.. Ich habe mein Sarkasmus-Schild verlegt..)
Im Ernst: Alle glücklich machen zu wollen führt längerfristig zu Problemen. Man kann nicht alle Ansichten berücksichtigen, sondern muss Entscheidungen treffen. Und mir gefällt der Gedanke grundsätzlich nicht, zwei Dinge für den exakt gleichen Zweck anzubieten. Als Benutzer ist man tendentiell verunsichert und fragt sich, ob ein Unterschied in der Funktionalität besteht. Ich verstehe heute noch nicht, warum
std::stringsize()undlength()hat.Wobei es hier natürlich weniger schlimm ist, weil das eine ein Operator ist – da hast du Recht. Die STL verwendet z.B. auch
assign(), um Zuweisungen mit mehreren Argumenten durchführen zu können. Ich muss mir wahrscheinlich nochmals in Ruhe durch den Kopf gehen lassen, ob eine zusätzliche benannte Methode wirklich Vorteile brächte. Möglicherweise werde ich sie zuerst weglassen, dann kann ich immer noch schauen...Wie gesagt bei Operatoren finde ich das überhaupt nicht verwirrend (ansonsten stimme ich dir zu und finde das ebenfalls komisch). Im Gegenteil bei einem Operator würde ich sogar eine benannte Funktion erwarten. Es kann durchaus Fälle geben, wo das wünschenswert sein kann. Bei einem Smart Pointer eher weniger, aber wie du sagst bei assign oder Sachen, welche ein Argument bekommen macht es durchaus Sinn. (Da finde ich den Weg, den Eiffel geht noch sehr schön. Dort macht man einfach eine Funktion und sagt dann, dass man sie auch mit einem Operator aufrufen kann. Keine Verwirrung, sondern es ist immer klar, dass es das gleiche ist).
Imo ist es bei keiner anderen Klasse, wie einem Smart Pointer so deutlich, dass er mindestens diesen Operator unterstützen muss. Alles andere wäre sehr kontraintuitiv.
-
Nexus du hast dich gerade als Noob geoutet. Es gibt keine if-Schleifen, sondern nur if-Abfragen!
-
Hallo zusammen,
Stilfrage: if (ptr) oder if(ptr != NULL)
Meine Antwort:
if (ptr) kann ich deutlich einfacher lesen und verstehen als: if(ptr != NULL)Warum ?
1. Keine Negierung in der Bedingung
2. kein zweiter - wenn auch einfacher - Operand
3. kürzer und deshalb einfacher und schneller zu lesen.if (!ptr) kann ich etwas einfacher lesen und verstehen als: if(ptr == NULL)
Warum ?
1. Ich muss negieren oder ich muss mit einem zweiten, einfachen Operanden vergleichen, was aufs gleiche heraus kommt.
2. besser finde ich dennoch die erste Variante, weil kürzer und deshalb einfacher und schneller zu lesen.Naja, ist nur so meine Ansicht.
Letzenendes sollte und MUSS das jeder so für sich halten können wie er will.
Es können gerade an diesen Stellen einfach nur unnötige Fehler enstehen,
wenn die API einem eine Logik aufzwingt, die man nicht gewoht ist.Deshalb, bitte beide Varianten anbieten.
Danke, Gruß Frank
-
Unglaublich...
Der Thread ist seit über 12 Stunden auf und noch keine Beschwerde,
dass es nicht äquivalent ist, weil der Standard (afaik) ja nicht vorschreibt,
dass NULL auch 0 sein muss.
Cool...
Ich dachte der Thread endet in so einer ewigen Diskussion...
EDIT: Ich bevorzuge:
if(ptr) if(!ptr)(Ich werde nie einen Compiler verwenden, wo NULL != 0 ist)
EDIT: Außerdem verwende ich 0 und nicht NULL
-
CSpille schrieb:
Unglaublich...
Der Thread ist seit über 12 Stunden auf und noch keine Beschwerde,
dass es nicht äquivalent ist, weil der Standard (afaik) ja nicht vorschreibt,
dass NULL auch 0 sein muss.
Das hast Du falsch verstanden.
Ein Nullzeiger muß zwar intern nicht als 0 repräsentiert werden, aber immer wenn 0 in einem Zeigerkontext verwendet wird, wird die 0 in einen Nullzeiger umgewandelt, der wie gesagt nicht 0 sein muß, aber logischerweise beim Vergleich mit ==0 doch true sagt, weil die rechte 0 vor dem Vergleich erst in einen Nullzeiger umgewandelt wird. Damit ist für Dich das Wissen, daß NULL nicht unbedingt 0 sein muß, gar nicht Teil des beobachtbaren Verhaltens.
Höchstens im Debugger könnte man vor Schreck vom Stuhl fallen, wenn sofort nach ptr=0 in ptr eine 0xdeadbeef steht.
-
Danke für die vielen Antworten. Es scheinen doch sehr viele Leute die Variante 1) zu verwenden, das hätte ich zuerst nicht gedacht.
volkard schrieb:
Mit 1) schaue ich, ob der Zeiger gültig oder ungültig ist, ob er auf etwas zeigt oder auf nix. Ob es den pointee gibt oder nicht. Ob der Auftrag noch zu erledigen ist oder schon weg. Und so weiter.
Mit 2) schaue ich, ob der Zeiger auf *NULL zeigt. Also in Bäumen, verketteten Listen und so, wo in der Doku explitzit steht, daß NULL das Ende anzeigt.
Das scheint mir eine sehr sinnvolle Vorgehensweise zu sein. Sowas kann ich mir ernsthaft für meinem eigenen Code überlegen...
volkard schrieb:
Wobei ich aber nie NULL nehme, sondern nur 0 und bald nullptr.
Warum nicht schon jetzt? Ist natürlich nicht so gut wie in C++0x, aber viel besser als
NULLund0.const class nullptr_t { public: // Konvertierbar in Datenzeiger template <typename T> operator T* () const { return 0; } // Konvertierbar in Zeiger auf Member template <class C, typename T> operator T C::* () const { return 0; } private: // Nicht adressierbar void* operator& (); } nullptr = {};Zu gefrickelt?

volkard schrieb:
Ich bin auch gegen Umdrehen wie bei if(0==ptr), weil das zu untersuchende Objekt ganz links beim Lesen hilft, so wie das empfangende Objekt in Zuweisungen ganz links, zum Beispiel if(0<=auszahlung-kontostand) versus if(auszahlung>=kontostand). Den extrem seltenen Zuweisungsfehler da wegzumachen, indem man mit so einem großen Hammer draufhaut und den Lesefluß==Debugfluß signifikant stört, ist nicht mehr gerechtfertigt.
Genau, so ähnlich habe ich im anderen Thread argumentiert.

Frank Erdorf schrieb:
Meine Antwort:
if (ptr) kann ich deutlich einfacher lesen und verstehen als: if(ptr != NULL)Warum ?
1. Keine Negierung in der Bedingung
2. kein zweiter - wenn auch einfacher - OperandAh, noch mehr Argumente für 1).

Frank Erdorf schrieb:
Es können gerade an diesen Stellen einfach nur unnötige Fehler enstehen,
wenn die API einem eine Logik aufzwingt, die man nicht gewoht ist.Deshalb, bitte beide Varianten anbieten.
Nun ja, beim Verwenden einer Bibliothek muss man sich eben an dortige Konventionen halten. Das beginnt schon bei der Namenskonvention, geht weiter über die Verwendung diverser Sprachmittel, über Codestil allgemein. Benutzt die Bibliothek Exceptions? Smart-Pointer? Werden Callbacks über Funktionszeiger, implementierte Interfaces oder
std::tr1::functionrealisiert? Implizieren Zeiger in der Schnittstelle, dassNULLerlaubt ist?
-
Nexus schrieb:
..., ob ich den Konvertierungsoperator
SmartPtr::operator SafeBool() const;mit all seinen Problemen, ...
Nicht mehr "lange", mit dem neuen Standard bekommen wir
explicitfür die Konvertierungsoperatoren. Ich denke, dass man hier schon etwas zukunftsausgerichtet denken darf.Ich mache es übrigens meistens so, wie volkard es beschrieben hat. Wenn der Nullzeiger einen Fehlerfall andeutet oder eine Gültigkeit, dann wird er einfach geprüft. In allen anderen Fällen vergleiche ich den Zeiger mit der
nullptrStruktur. Und ich bin inzwischen sogar wieder vomnullptr == ptrTripp abgekommen. Zu viele Leute scheinen damit Probleme beim Lesen zu haben und ich denke daher, dass hier die Wartbarkeit über die Fehlerprävention gewinnt
Grüssli
-
Dravere schrieb:
Nicht mehr "lange", mit dem neuen Standard bekommen wir
explicitfür die Konvertierungsoperatoren. Ich denke, dass man hier schon etwas zukunftsausgerichtet denken darf.Ich weiss nicht, ob ich in der Bibliothek schon bald C++0x verwende. Wahrscheinlich würde ich die User stark dezimieren...
Dravere schrieb:
Und ich bin inzwischen sogar wieder vom
nullptr == ptrTripp abgekommen.In meinen Anfängen verwendete ich
NULL, dann0, späternullptrund jetzt für die Bibliothek wiederNULL(sonstnullptr). Und in Zukunft werde ich wahrscheinlich implizit abfragen.
-
Nexus schrieb:
Dravere schrieb:
Nicht mehr "lange", mit dem neuen Standard bekommen wir
explicitfür die Konvertierungsoperatoren. Ich denke, dass man hier schon etwas zukunftsausgerichtet denken darf.Ich weiss nicht, ob ich in der Bibliothek schon bald C++0x verwende. Wahrscheinlich würde ich die User stark dezimieren...
Aktuell wird
explicitnur vom GCC 4.5 unterstützt. Aber ich meinte auch nicht, dass du bereitsexpliciteinsetzen sollst. Aber man kann aktuell das Safe-Bool-Idiom verwenden und halt im Hinterkopf behalten, dass dies nicht ein Workaround für alle Zeiten ist, sondern nur bis der neue Standard sich etabliert hat. Damit halt der üble Geschmack ein wenig besser wird
Nexus schrieb:
Dravere schrieb:
Und ich bin inzwischen sogar wieder vom
nullptr == ptrTripp abgekommen.In meinen Anfängen verwendete ich
NULL, dann0, späternullptrund jetzt für die Bibliothek wiederNULL(sonstnullptr). Und in Zukunft werde ich wahrscheinlich implizit abfragen.
Ich meinte wegen dem
nullptr == ptr<->ptr == nullptr
nullptrverwende ich schon noch weiterhin, wie ich es im meinem vorherigen Beitrag geschrieben hatte.Grüssli
-
Nexus schrieb:
Dravere schrieb:
Nicht mehr "lange", mit dem neuen Standard bekommen wir
explicitfür die Konvertierungsoperatoren. Ich denke, dass man hier schon etwas zukunftsausgerichtet denken darf.Ich weiss nicht, ob ich in der Bibliothek schon bald C++0x verwende. Wahrscheinlich würde ich die User stark dezimieren...
OpenSource
