Stack-Objekte in while-Schleife und Exceptions
-
Dann krieg ich aber Probleme mit pure virtual...
Oder liegt in diesem Fall schlechtes Design vor?
thordk schrieb:
im ersten beispiel haben die objekte nicht immer dieselbe adresse. es kann passieren, ist aber nicht garantiert.
Gibt es ne Regel, wann es so ist und wann nicht?
-
ReferenceProblem schrieb:
Gibt es ne Regel, wann es so ist und wann nicht?
nicht dass ich wüsste.
das lokale objekt wird bei verlassen des scope zerstört. das geschieht bei jedem schleifendurchlauf. beim nächsten aufruf wird sie wieder angelegt. dabei könnte sie u.u. an derselben stelle im speicher angelegt werden und vielleicht macht nen compiler das auch so beim optimieren. aber garantiert ist da nix.
-
thordk schrieb:
ReferenceProblem schrieb:
Gibt es ne Regel, wann es so ist und wann nicht?
nicht dass ich wüsste.
das lokale objekt wird bei verlassen des scope zerstört. das geschieht bei jedem schleifendurchlauf. beim nächsten aufruf wird sie wieder angelegt. dabei könnte sie u.u. an derselben stelle im speicher angelegt werden und vielleicht macht nen compiler das auch so beim optimieren. aber garantiert ist da nix.
Probier einfach nen kleines Beispielprogramm zu basteln wo die Adresse NICHT gleich ist. Würde mich wundern wenn das recht einfach geht

Garantie gibts trotzdem keine, d.h. man sollte sich auch nicht drauf verlassen.Und es ist ziemlich wurscht in dem Fall, da es auch nix helfen würde wenn sich die Adresse jedes mal ändert -- wenn die Schleife bei Durchlauf 10 ist sind die 9 Objekte die davor "dort gelebt haben" schon längst zerstört und deine collection hält 9 dangling pointers. Solange diese dangling pointers nicht dereferenziert oder rumgereicht oder sonstwie "angegriffen" werden ist das OK, bloss dann wäre die ganze collection fürn Hugo.
@ReferenceProblem:
Ein paar Ansätze:
* Du könntest shared ownership verwenden (z.b. mit boost::shared_ptr)
* Du könntest (member) function pointer statt virtual pure verwenden
* Du könntest nen Guard verwenden
-
Hallo hustbaer,
ich mach mir mal Gedanken über deine Vorschläge...
Allerdings kann ich mithustbaer schrieb:
* Du könntest nen Guard verwenden
garnichts anfangen.
Ich kenn nur Include-Guards und mit der Suche bin ich auch nicht
fündig gewordenKann mir jemand erklären, was ein Guard ist?
-
thordk schrieb:
...
void add(Object o);ReferenceProblem schrieb:
Dann krieg ich aber Probleme mit pure virtual...
Kannst Du das mal kurz erklären ?
Mir fällt so spontan kein Fall ein, wo das zusammenfallen könnte ...Außerdem ist mir nicht klar, was Deine Klasse in der Memberfunktion mit der Referenz macht ....
Gruß,
Simon2.
-
Vielleicht steh ich aufm Schlauch, aber
bei nem einfachen Listener ist das doch so...Denn bei pure virual hast du ja keinen verwendbaren Copy-Konstruktor
-
ReferenceProblem schrieb:
...hast du ja keinen verwendbaren Copy-Konstruktor
Ach so - Deine Klasse hat keinen CopyCtor.

Das hatte ich nicht mit "pure virtual" verbunden (dachte da eher an einzelne Memberfunktionen) ....
Aber so stimmt das natürlich.
Danke,
Simon2.
-
Ein Guard ist ne (mehr oder weniger) kleine Hilfsklasse die dafür sorgt dass gewisse Dinge immer gemacht werden/nicht gemacht werden können.
z.B. könntest du dir eine Guard Klasse programmieren der du Zeiger auf deine Instanzen übergibst, und die dann ownership übernimmt. Weiters teilst du dieser Guard Klasse mit welcher anderen Collection du diese Zeiger übergibst, damit die Guard Klasse vor dem löschen der Objekte diese auch wieder aus der Collection entfernen kann.Pseudocode:
class Guard { Guard(Collection& c) : m_collection(c) { } ~Guard() { for all Objects o in m_objects { m_collection.Remove(o); delete o; } } void AddLocalToCollection(Object* o) { m_objects.push_back(o); m_collection.Add(o); } Collection& m_collection; vector<Object*> m_objects; }So inetwa
-
Hallo HustBaer...
Vielen Dank für die ausführliche Erklärung!!!
Eigentlich ganz easy

-
Argh!
AddLocalToCollection ist ein scheiss Name, da ist mir wohl noch dein "Stack Objekte" im Kopf rumgeschwirrt - is ja aber nicht "local" sondern "ge-newt" (schönes Wort
). Sollte vielleicht besser einfach nur Add oder AddAndTakeOwnership heissen.Und die Sequenz "push_back" + "Add" ist nicht exception-safe, ist so vielleicht besser:
class Guard { Guard(Collection& c) : m_collection(c) { } ~Guard() { for all Objects o in m_objects { if (o) { m_collection.Remove(o); delete o; } } } void AddAndTakeOwnership(Object* p) { auto_ptr<Object> guard(p); // damit o in jedem Fall gelöscht wird m_objects.push_back(0); m_collection.Add(p); // jetzt kann nixe mehr schiefgehen guard.release(); m_objects.back() = p; } Collection& m_collection; vector<Object*> m_objects; }Is etwas gefrickelt, dafür aber jetzt exception safe

-
hustbaer schrieb:
...aber jetzt exception safe

Dazu noch eine Bemerkung @ReferenceProblem: Du solltest Dir auch überlegen, was der Aufrufer Deiner Funktion erwarten soll, wenn er eine Exception "zurückbekommt" ... welchen Zustand hat dann der Container ? Welchen die betroffene(n) Klasse(n) ?
Das klingt erstmal trivial, aber wenn man sich das genauer ansieht, entwickelt sich eine größere Herausforderung....Gruß,
Simon2.