object am stack anlegen unterbinden/erschweren
-
Meep Meep schrieb:
ich habe eine hand voll klassen die ich nicht am stack erstellen lassen will.
Tönt sehr nach falschem Design. Warum?
-
why schrieb:
Meep Meep schrieb:
ich habe eine hand voll klassen die ich nicht am stack erstellen lassen will.
Tönt sehr nach falschem Design. Warum?
weil es teil eines frameworks ist und die objecte groß und langlebig sind.
was mich an der statischen factory methode stoert ist, das ich dann unterschiedliche erstellungswege habe. dann muss man immer ueberlegen
was man mit new und was man mit create erstellt.Meep Meep
-
Und warum sorgen die Objekte nicht selber dafür, dass der grosse Teil auf'm Heap angelegt wird?
-
auf http://www.cpp-tutor.de/cpp/le12/ueberl_spez.html steht:
Die Operatoren new und delete können für eine Klasse nur durch eine statische Memberfunktion überladen werden. Auch wenn die Memberfunktion nicht explizit als statisch deklariert wird, wird sie durch den Compiler immer als solche angelegttheoretisch muesste dann der operator new auf den privaten constructor
zugreifen koennen. aber auch wenn das aus irgendeinem grund nicht der fall sein
sollte koennte man das so machen:class test { public: int val; test(const test&) = delete; test(test&&) = delete; static test* create(void) { return new test(); } void* operator new(size_t size) { return test::create(); } private: test(void) : val(0) { } public: ~test(void) { } }; /* class test */test::create kann ja auf jeden fall ein object anlegen. aber so funktioniert
das auch nichterror C2248: "test::test": Kein Zugriff auf private Member, dessen Deklaration in der test-Klasse erfolgte. 1> d:\nachtschatten\programming\gromit\gromit\main.cpp(36): Siehe Deklaration von 'test::test'das versteh ich jetzt aber ueberhaupt nicht wo da das problem liegt.
test::create ist schliesslich public.
-
Meep Meep schrieb:
operator new
Das ist der völlig falsche Ansatz. Overengineering, Overkill, den Nutzer bevormundend, etc.
Technisch spricht sicher nichts dagegen, das auf dem Stack anzulegen (den entsprechenden Speicher kannst du ja intern auf den Heap legen). Die Lebensdauer bestimmt der Anwender. Vielleicht gibt es ja in irgend einem Umstand einen guten Grund, das in einer bestimmten Situation auf dem Stack anzulegen. Das dann zu verbieten wäre unnötig.
Lass die Idee einfach fallen.
Wenn Kopie keinen Sinn macht, lösche den Kopierkonstruktor/Kopierzuweisung. Wenn Move keinen Sinn macht, dann auch das. std::mutex ist z.B. nicht movable, aber lässt sich trotzdem auf dem Stack anlegen (und das ist auch oft gut so).
Wenn das nicht genug ist, dann soll man das halt manuell auf dem Heap anlegen.
-
Bitte vollständiges Minimalbeispiel!
Und beantworte bitte Jockelxs Frage!
-
Einfache Lösung: Mach das Ding so groß, daß es bei den Standareinstellungen aller gänigen Compiler nicht mehr auf den Stack passt.

-
Swordfish schrieb:
Einfache Lösung: Mach das Ding so groß, daß es bei den Standareinstellungen aller gänigen Compiler nicht mehr auf den Stack passt.


class test { public: int val; test(const test&) = delete; test(test&&) = delete; static test* create(void) { return new test(); } void* operator new(size_t size) { return test::create(); } private: test(void) : val(0) { } public: ~test(void) { } }; /* class test */ int main(void) { test *t1 = new test(); }ich dachte das ich so mit dem ueberladenen new eine instanz erzeugen kann. aber
ich denke mal das das problem hier die compilermagie ist, die den constructor
selbst aufruft. new gibt ja eigendlich nur nen raw-speicher zurueck wenn ich
das richtig verstanden habe. also wird es danmn nichts bringen wenn ich in
operator new eine instanz der klasse erzeugen lasse, weil dann trotzdem
irgendwie nochmals der constructor fuer den zurueckgegebene speicher aufgerufen
werden wird und da kommt dann auch wieder das problem mit dem privaten
constructor.ich werde es wohl mit dem privaten destructor machen
Meep Meep
-
Jockelx schrieb:
Und warum sorgen die Objekte nicht selber dafür, dass der grosse Teil auf'm Heap angelegt wird?
wie schon gesagt gehoeren die klassen zu einem framework. die verbindung
untereinander ist aehnlich wie bei einem baum. funktionieren auch zum teil als knotenklassen.
die klassen verwalten sich hierbei selber. wenn ich einen knoten loesche dann loescht er zuerst alle objecte die unter sich sind. ich kann nun eigene objecte einfuegen. ob die nun auf dem stack oder am heap liegen ist da noch egal.
das problem erfolgt dann bei der zerstoerung der objekte. ich muesste buchfuehren ob ein objekt am stack oder am heap erstellt worden ist. meines wissens gibt es keine moeglichkeit, das ohne weiteres rauszufinden.kurz um: es ist eine design entscheidung die ich nun mal gefaellt habe und die mir ansich gefaellt
-
Meep Meep schrieb:
wie schon gesagt gehoeren die klassen zu einem framework. die verbindung
untereinander ist aehnlich wie bei einem baum. funktionieren auch zum teil als knotenklassen.
die klassen verwalten sich hierbei selber. wenn ich einen knoten loesche dann loescht er zuerst alle objecte die unter sich sind. ich kann nun eigene objecte einfuegen. ob die nun auf dem stack oder am heap liegen ist da noch egal.
das problem erfolgt dann bei der zerstoerung der objekte. ich muesste buchfuehren ob ein objekt am stack oder am heap erstellt worden ist. meines wissens gibt es keine moeglichkeit, das ohne weiteres rauszufinden.Also ein intrusiver Container? Da wäre es aber ein Fehler im Design, wenn der Container selber anfängt, Elemente zu löschen. Die Elemente einer intrusiven Datentstruktur gehören nicht der Datenstruktur, sondern die Datenstruktur ist aus diesen Objekten aufgebaut, die aber unabhängig von diesem existieren.
-
Meep Meep schrieb:
ich kann nun eigene objecte einfuegen. ob die nun auf dem stack oder am heap liegen ist da noch egal.
Nein, das ist nicht egal.
Du verbietest einfach (in der Doku!) dass Objekte übergeben werden die am Stack liegen.
Und als "dezenten aber schwer übersehbaten Hinweis"
lässt du die Ownership-übernehmenden Funktionen einen besitzenden Smart-Pointer (z.B. std::unique_ptr) als Parameter nehmen. => Problem gelöst.Wenn jmd. dann ausserhalb von diesem Anwendungsszenario eines dieser Objekte (z.B. den Rootknoten) auf den Stack legen will, dann soll er doch. Kann dir Schnuppe sein.
-
SeppJ schrieb:
Die Elemente einer intrusiven Datentstruktur gehören nicht der Datenstruktur, sondern die Datenstruktur ist aus diesen Objekten aufgebaut, die aber unabhängig von diesem existieren.
Naja, gibt solche und solche intrusive Container.
Kann schon sinn machen einen besitzenden solchen zu haben.
Wobei die Basis vermutlich erstmal immer ein nicht besitzender sein sollte. Denn da einen besitzenden draus zu machen ist dann ein 5-Zeiler oder so (mehr je nach Anzahl der Konstruktoren). Und umgekehrt geht's halt nicht (bzw. muss man die Containerklasse dazu umschreiben, was fies ist wenn man es nicht darf/kann).Als grundsätzlich sinnlos oder gar falsch würde ich besitzende Intrusive-Datenstrukturen aber nicht ansehen.
-
SeppJ schrieb:
Meep Meep schrieb:
wie schon gesagt gehoeren die klassen zu einem framework. die verbindung
untereinander ist aehnlich wie bei einem baum. funktionieren auch zum teil als knotenklassen.
die klassen verwalten sich hierbei selber. wenn ich einen knoten loesche dann
loescht er zuerst alle objecte die unter sich sind. ich kann nun eigene objecte
einfuegen. ob die nun auf dem stack oder am heap liegen ist da noch egal.
das problem erfolgt dann bei der zerstoerung der objekte. ich muesste
buchfuehren ob ein objekt am stack oder am heap erstellt worden ist. meines
wissens gibt es keine moeglichkeit, das ohne weiteres rauszufinden.Also ein intrusiver Container? Da wäre es aber ein Fehler im Design,
wenn der Container selber anfängt, Elemente zu löschen.mit intrusiver container kann ich jetzt gerade nicht viel anfangen. muss morgen
mal nachlesen was das genau bedeutet.
von alleine faengt da auch nichts an zu loeschen. ich selber bestimme wann und
welches object geloescht wird. nur das ich mich dann nicht mehr um das loeschen
bzw. freigeben der objekte kuemmern muss.
ich werde mir ueber den ganzen ansatz nochmal den kopf zerbrechen. danke fuer
die anregungen.Meep Meep
-
Intrusive Container sind solche, die keine Kopien der Daten speichern, sondern bei dem direkt die Daten selber den Container aufbauen. Dazu müssen die Daten natürlich die benötigten Schnittstellen für die Verwaltungsdaten mitbringen, damit der Container aus den Daten seine Struktur bilden kann.
Einer der großen Vorteile der Geschichte ist, dass der Anwender die Steuerung darüber hat, wo die Daten liegen, anstatt dass der Container sich über seinen Allocator wer weiß wo Speicherplatz besorgt. So kann der Anwender beispielsweise alle Elemente in ein Array packen und die Elemente dann an eine intrusive Liste geben und hat dann die Vorteile einer Listenstruktur, aber alles schön lokal beisammen!
Der große Nachteil ist, dass der Container kein abgeschlossenes Objekt mehr ist, es liegt also eine deutlich höhere Verantwortung beim Benutzer, den Container richtig zu nutzen. Was du hier anscheinend mit Gewalt erzwingen möchtest, obwohl eine Dokumentation der richtigen Anwendung wohl auch reichen würde.Es gibt auch noch andere vor- und Nachteile, eine Übersicht und Einführung findest du hier:
http://www.boost.org/doc/libs/1_57_0/doc/html/intrusive/intrusive_vs_nontrusive.html
Deine Beschreibung klingt ganz so, als läge bei dir eine Art von intrusiver Container vor? Hast du den selber geschrieben? Oder benutzt du was fertiges? Falls ja, was?