Nullpointer?
-
Jockelx schrieb:
Solange du keine virtuellen Funktionen aufrufst und die Funktionen keine Member nutzen, passiert da idR nix.
Ist aber imo undefiniertes Verhalten.
-
obj* o = 0; // Verweis auf "nichts"?ist richtig
o->invoke(); // hier Ausnahme!?Nein, nur undefiniertes Verhalten. Du darfst den Pointer nicht dereferenzieren, weil er 0 ist. Soviel zur Theorie. In der Praxis weiß der Compiler, dass er für obj::invoke nicht wissen muss, wohin der Pointer zeigt (weil keine Membervariablen, Basisklassen oder virtuelle Funktionen betroffen sind) und wird den Pointer deshalb auch nicht dereferenzieren. Deshalb stolpert er auch nicht über die Tatsache, dass der nirgendwohin zeigt.
delete o; // hier nicht, delete kann auf Nullpointer angewendet werden.Richtig. Ist im Standard so definiert, dass delete auf Nullpointer okay und wirkungslos ist.
-
Vielen Dank.
Das die Memberfunktionen im Prinzip über invoke(o) aufgerufen wird, hat mir die Augen geöffnet.
-
_) schrieb:
Vielen Dank.
Das die Memberfunktionen im Prinzip über invoke(o) aufgerufen wird, hat mir die Augen geöffnet.Muss aber nicht so sein - so ist es einfach bei den meisten Implementationen.
-
Okay, vielen Dank für eure Antworten. : )
Nun eine Frage zum "Stil"; eine Klasse verwaltet eine Liste von Pointern, in wie weit könnte ich dann Probleme kriegen, wenn ich per "new" Objekte referenziert hinzufüge?
//... includes ... class obj { // Klasse mit Member und Funktionen }; class pmap { private: vector<obj*> _list; public void add(obj* p) { _list.push_back(p); } obj* get(int i) { // ... argument check return _list[i]; } // .... ~pamp() { // ... delete auf alle Elemente aus _list } }; int main() { // ... pmap.add(new obj); // ... pmap.get(1)->...; }Schlechter Stil oder vollkommen in Ordnung?
Im Prinzip fühle ich mich wohl damit, aber vielleicht zu Unrecht, vielleicht sehe ich etwas nicht?
-
Du solltest sie (i.d.R.) sogar mit new Anlegen, da die Lebensdauer sonst auf den Scope {} beschränkt ist.
Löschen (delete) aber nicht vergessen!!!
(Oder gleich boost::ptr_vector verwenden)
-
Das einzige problem was ich sehe ist, wenn list::push_back eine Exception wirft, was nur sein kann, wenn der Speicher ausgeht. Dann wäre der Pointer auf das grade neu angelegte Objekt flöten und du hättest ein Speicherleck.
-
O.o schrieb:
Schlechter Stil oder vollkommen in Ordnung?
Im Prinzip fühle ich mich wohl damit, aber vielleicht zu Unrecht, vielleicht sehe ich etwas nicht?3 Dinge:
- Ausnahmesicherheit (siehe pumuckls Beitrag)
- Hast Du auch die Dreierregel beachtet?
- Warum heist das Ding "pmap" wenn es "pvec" hätte heißen können?
-
Erstmal danke für die Antworten.

Also wenn ich folgendes mache:
// wie oben. int main { // eigene scope .. { obj* p = new obj; pmap.add(p); } // obj tot? }Und anders, was passiert, wenn ich das Objekt von außen lösche; könnte es sein, dass dann mein Zeiger irgendwann auf was ganz anderes zeigt?
int main { obj* p = new obj; pmap.add(p); delete p; /* ... nun erstelle ich andere Objekte vom Typ obj2, welcher nichts mit obj zu tun hat. Zeigt dann der gerade hinzugefügte Pointer irgendwann in so ein obj2 hinein? */ }
-
Nachtrag als Antwort auf krümelkacker:
- Exceptions, wird implementiert.
- Dreierregel kannte ich bisher nicht. Notiert. Danke dafür.
- Die Grundidee war auf einer map basiert.
-
Und anders, was passiert, wenn ich das Objekt von außen lösche; könnte es sein, dass dann mein Zeiger irgendwann auf was ganz anderes zeigt?
Ja. Du darfst den Zeiger nicht mehr dereferenzieren!
nun erstelle ich andere Objekte vom Typ obj2, welcher nichts mit obj zu tun hat. Zeigt dann der gerade hinzugefügte Pointer irgendwann in so ein obj2 hinein?
Nein.
-
o.O schrieb:
- Exceptions, wird implementiert.
Exceptionsicherheit ist was anderes, als selber Exceptions zu schmeißen. Es geht da drum, wie gutartig sich dein Programmm im Ausnahmefall verhält. Siehe zum Beispiel erste Antwort hier:
http://stackoverflow.com/questions/1853243/c-do-you-really-write-exception-safe-code
-
Ihr scheint zu vergessen, dass sein Objekt 0 Bytes groß ist. Was würde denn new in diesem Fall zurückgeben? Wohl auch nen Dummywert, den man eigentlich nicht dereferenzieren dürfte, also wirds wohl kein undefiniertes Verhalten sein ...
-
Ethon schrieb:
Ihr scheint zu vergessen, dass sein Objekt 0 Bytes groß ist. Was würde denn new in diesem Fall zurückgeben? Wohl auch nen Dummywert, den man eigentlich nicht dereferenzieren dürfte, also wirds wohl kein undefiniertes Verhalten sein ...
Objekte sind nie 0 Byte groß. Zur Not haben sie eine Dummygröße.
edit: Und man sollte vielleicht noch erwähnen, dass eine leere Klasse als Basisklasse wiederum eine Größe von 0 haben darf.
-
Vieleicht gehört hier noch erwähnt, dass das die EBO (Empty Base Optimization) ist, die bei manchen Compilern bei Mehrfachvererbung und komplizierteren Hierarchien leider nicht mehr greift.
-
Das Zeug von O.o ist nicht mal compilationsfähig, wenn der Destruktor
~pamp() { // ... delete auf alle Elemente aus _list }heißt, vermute ich...