Der this-Zeiger im if
-
Na irgendwo steht bestimmt auch noch geschrieben, dass kein Objekt an der Objekttypsezifischen Adresse 0 zu finden sei. Das heißt, wenn this == 0, dann kann da kein Objekt sein für das die Methode aufgerufen wurde und this soll aber auf "das" Objekt zeigen laut 5.5.2.
Irgendwie so?
-

4.10 Pointer conversions [conv.ptr]
1 A null pointer constant is an integral constant expression (5.19) prvalue of integer type that evaluates to zero or a prvalue of type std::nullptr_t. A null pointer constant can be converted to a pointer type; the result is the null pointer value of that type and is distinguishable from every other value of object pointer or function pointer type.
-
Hrmmm, ich weiß nicht ob daraus allein schon hervor geht, dass da nicht auch ein Objekt sein darf.
-
#include <iostream> using std::cout; struct Test{ void bla(){ cout << "bla\n"; } }; int main(){ Test *t = 0; t->bla(); }Das ist UB? Für mich sieht das wir korrektes C++ aus, aber ich lese auch den Standard nicht.
-
Decimad schrieb:
Hrmmm, ich weiß nicht ob daraus allein schon hervor geht, dass da nicht auch ein Objekt sein darf.
ich denke mal, wenn da steht "null pointer value of that type and is distinguishable from every other value of object pointer or function pointer type", dann darf da kein Objekt sein. es gibt ja auch z.B. bei op new und op delete spezielle Regeln für Nullpointer, die nur dann funktionieren, wenn der Nullpointer per Def. ungültig ist
-
nwp3 schrieb:
Das ist UB? Für mich sieht das wir korrektes C++ aus, aber ich lese auch den Standard nicht.
Sieht folgender Code für dich auch korrekt aus?
Test* t = nullptr; funktion(*t);Wie stehts mit diesem?
Test* t = nullptr; (*t).funktion();
-
Ich liebe Rätsel! Wie steht es mit
struct A { void f () { } }; int main () { A* ap = 0; ap->f (); }?
-
@Nexus & @beispiellos
Sieht beides nach korrektem C++ ohne UB aus.
-
Welches Verhalten erwartest du denn bei der Dereferenzierung eines Nullzeigers?
-
@nwp3: Jackpot! Das Beispiel habe ich von hier, mit Kommentar vom Komitee.
Eine Referenz auf 0 ist nicht per se UB, erst wenn auf sie irgendwie zugegriffen wird.
Also ist es vollkommen richtig, this auf 0 zu testen und erst nachher darauf zuzugreifen

-
Aus meiner Praxis: Ich lasse goto einmal im Jahr stehen. Ich lasse switch vielleicht zweimal im Jahr stehen. Aber eine Prüfung auf this==0 nicht einmal überhaupt.
Ich fürchte, das muss man nur machen, wenn man das Gesamtkonzept verloren hat und versucht, Zugriffsfehler im Nachhinein an den Symptomen zu heilen.Ich stelle diesem Stil eine schlechte Prognose aus.
-
Nexus schrieb:
Welches Verhalten erwartest du denn bei der Dereferenzierung eines Nullzeigers?
Es gibt mit an Sicherheit grenzender Wahrscheinlichkeit einen Segfault, aber das ist nicht der Punkt. Das Programm wird von jedem korrekten C++-Compiler korrekt übersetzt und tut genau was da steht, einen Nullpointer dereferenzieren.
Steht denn im Standard dass man den Nullpointer nicht dereferenzieren darf? Was wenn ein Mikrokontroller sein bisschen RAM bei 0 anfangen lässt und darauf hardwaretechnisch auch zugreifen kann, dürfte man das laut Standard trotzdem nicht?
-
Na aber der Standard sagt doch, dass this mit dem Zeiger auf das Objekt belegt ist, in einer nicht-statischen Klassenmethode. 0 kann aber doch kein gültiger Zeiger auf ein Objekt sein?
Immer diese Grenzfälle...
-
nwp3 schrieb:
Nexus schrieb:
Welches Verhalten erwartest du denn bei der Dereferenzierung eines Nullzeigers?
Es gibt mit an Sicherheit grenzender Wahrscheinlichkeit einen Segfault, aber das ist nicht der Punkt. Das Programm wird von jedem korrekten C++-Compiler korrekt übersetzt und tut genau was da steht, einen Nullpointer dereferenzieren.
Steht denn im Standard dass man den Nullpointer nicht dereferenzieren darf? Was wenn ein Mikrokontroller sein bisschen RAM bei 0 anfangen lässt und darauf hardwaretechnisch auch zugreifen kann, dürfte man das laut Standard trotzdem nicht?Nee neen ee. Der Nullzeiger ist ein Zeiger, der unabhängib von der internen Repräsentaion anzeigt, daß da nix ist. Er muss intern nicht 0x0000000 sein. Kann auch ganz anders. Dann tut halt der Compiler für das Embedded-Ding (void*)0 nach 0xdeadbeef mappen oder so. Alles möglich.
-
volkard schrieb:
Aus meiner Praxis: Ich lasse goto einmal im Jahr stehen. Ich lasse switch vielleicht zweimal im Jahr stehen. Aber eine Prüfung auf this==0 nicht einmal überhaupt.
Ich fürchte, das muss man nur machen, wenn man das Gesamtkonzept verloren hat und versucht, Zugriffsfehler im Nachhinein an den Symptomen zu heilen.Ich stelle diesem Stil eine schlechte Prognose aus.
genau das hatte ich damals dem Projektleiter auch gesagt

-
#include <cstdio> Test* t; t = 0; t->f(); //korrekt, wenn auch nicht sinnvoll t = nullptr; t->f(); //UB t = NULL; t->f(); //???Soweit richtig? Nummer 3 wäre dann wohl auch UB.
-
volkard schrieb:
Nee neen ee. Der Nullzeiger ist ein Zeiger, der unabhängib von der internen Repräsentaion anzeigt, daß da nix ist. Er muss intern nicht 0x0000000 sein. Kann auch ganz anders. Dann tut halt der Compiler für das Embedded-Ding (void*)0 nach 0xdeadbeef mappen oder so. Alles möglich.
wie man z.B. unter 4.10 Pointer conversions nachlesen kann, kann man den Nullpointer mit "(int) 0" vergleichen
-
nwp3 schrieb:
Steht denn im Standard dass man den Nullpointer nicht dereferenzieren darf?
Ja, im alten Standard war die Nullzeiger-Dereferenzierung undefiniertes Verhalten. Eine Ausnahme war die Existenzgrundlage von
std::bad_typeid. Ich weiss nicht, in wie fern sich C++11 hier geändert hat, jedenfalls gab es mal diesen Vorschlag zur Klarstellung.volkard schrieb:
Ich fürchte, das muss man nur machen, wenn man das Gesamtkonzept verloren hat und versucht, Zugriffsfehler im Nachhinein an den Symptomen zu heilen.
Sehe ich auch so. Generell halte ich die Notwendigkeit, Zeiger immer gleich sofort auf Null zu setzen (nach
delete-- oder noch schlimmer -- im Destruktor) und jeweils zu prüfen, für fragwürdig. Oft ist das ein Hinweis darauf, dass man sich über die Gültigkeit seiner Zeiger nicht im Klaren ist. Hier habe ich etwas Ausführlicheres dazu geschrieben.
-
nwp3 schrieb:
#include <cstdio> Test* t; t = 0; t->f(); //korrekt, wenn auch nicht sinnvoll t = nullptr; t->f(); //UB t = NULL; t->f(); //???Soweit richtig?
Nein. Der Wert von t ist nach den Zuweisungen durch
0,NULLundnullptrjeweils derselbe. Das MakroNULList in C++ gerade als0definiert,nullptrist die typsichere C++11-Variante.
-
Nexus schrieb:
Generell halte ich die Notwendigkeit, Zeiger immer gleich sofort auf Null zu setzen (nach
delete-- oder noch schlimmer -- im Destruktor) und jeweils zu prüfen, für fragwürdig. Oft ist das ein Hinweis darauf, dass man sich über die Gültigkeit seiner Zeiger nicht im Klaren ist.Ein
delete p; p=0;bzw
safeDelete(p);//template!ist ein sicheres Zeichen dafür, daß ich diesem Projekt nicht beitrete. Und wenn sie mich genug anflehen, nehme ich mir eine Minute und sichte den bisherigen Code und finde ein new[]/delete-Paar oder eine integer-Division durch 0 oder eine Endlosschleife. Gamecoders halt.