delete mit Größenangabe?
-
Hallo,
ich will eine Art mehr oder weniger dynamische Möglichkeit bieten, Parameter verschiedenster Typen an eine Funktion zu übergeben. Dann soll nach Ablauf einer bestimmten Zeit eine Funktion aufgerufen werden, d.h. die Parameter müssen zwischengespeichert werden. Das ganze klappt ja so lange ganz gut, wie ich weiß, welchen Typ die Parameter haben. Aber was ist, wenn ich eine Möglichkeit bieten will, auch Typen zu supporten, die ich zur Compilezeit gar nicht kenne? Idee: Man übergibt einen Pointer, der pernewerstellt wurde und die Größe des Objekts. Nun möchte ich, wenn die Zeit um ist und eine bestimmte Funktion aufgerufen wurde, das unbekannte Objekt wieder löschen. Problem: der Compiler kennt die Größe des Typs ja nicht.Zentrale Frage: Wie sage ich
delete, dass es ab der Stelle X, also ab da, wo der Typ mitnewerstellt wurde, die Anzahl an Bytes löscht, die mir übergeben wurden?Gruß
-
Was soll die Grösse bringen? Du kannst ja nicht einfach ein Objekt per memcpy() kopieren...
Guck dir mal
boost::anyan.
-
Sowas geht entweder mit Templates (dann kannst wird auch der Destruktor aufgerufen) oder mit malloc/free (hier wird die Grösse mitgeschrieben.
Zweiteres würde ich dir nicht empfehlen, daher:
// Header: void my_ugly_pointer_func_do(void *ptr); // Nur dieser Teil ist templated, da sonst jedesmal die obere Funktion neu geschrieben werden muss template<typename T> void my_ugly_pointer_func(T *ptr) { my_ugly_pointer_func_do(ptr); delete ptr; // Destruktor wird aufgerufen, Compiler weiss von welchem Typ (wenn kein Array). } // Code: void my_ugly_pointer_func_do(void *ptr) { // hier dein alter Code }So sollte das gehen, mir will der Sinn aber nicht ganz erschliessen.
-
@ hustbaer: Das habe ich auch gar nicht vor. Ich habe mir das so vorgestellt:
// externe plugin.dll class Bla // Bla ist nur in plugin.dll bekannt, somit auch dessen Größe { public: // ... }; // ... void myCallback(void **) { } // ... bool *test = new bool; *bool = false; int *x = new int; *x = 2; Bla *bla = new Bla; pMyIface->CreateTimer(2.0/*delay*/, myCallback, Type_Bool, test, Type_Int, x, Type_AutoDeletePointer, bla); // ... typedef void (*Callback_t)(void **); void MyIface::CreateTimer(double delay, Callback_t Callback, ...) { // daten speichern } void MyIface::OnTick() { for (/* daten durchlaufen*/) { if (bla.delay + currenttime <= currenttime) { bla.callback(bla.params); // an dieser stelle müsste ich dann alle parameter durchgehen, um diese mit delete wieder zu löschen // bei bool, int, float, double, long, und so, weiß ich ja, wie groß sie sind, d.H. ich kann folgendes machen: delete (long*)blub; // bei eigenen Typen weiß der Compiler ja nicht, wie groß diese sind // also bräuchte ich etwas, was dem delete folgendes sagt: // ab hier z.B. 250 bytes löschen delete (void*)blub; } } }Gruß
-
Eigentlich müsste deine Speicherverwaltung selber die allokierte Größe kennen. Wenn ich
delete [] foo;schreibe teile ich ja auch nicht dem Compiler die Anzahl der Elemente mit.
-
theliquidwave schrieb:
ich will eine Art mehr oder weniger dynamische Möglichkeit bieten, Parameter verschiedenster Typen an eine Funktion zu übergeben. Dann soll nach Ablauf einer bestimmten Zeit eine Funktion aufgerufen werden, d.h. die Parameter müssen zwischengespeichert werden.
Das klingt nach dem, was boost::thread auch schon macht. Der Konstruktor nimmt ein beliebiges Funktionsobjekt optional mit zusätzlichen Parametern entgegen und speichert diese zwischen, so dass der neu gestartete Thread darauf später arbeiten kann. boost::function und boost::any arbeiten ähnlich. Der Trick heißt "type erasure" in C++. In Java gibt es diesen Begriff auch, hat dort aber eine leicht andere Bedeutung. Ich bin mir auch sicher, dass das in diesem Forum mindestens 2mal schon erklärt wurde. Such mal danach.

-
Zum Löschen reicht es doch nicht wenn du die Grösse kennst, es muss ja u.U. auch ein Destruktor laufen.
Verwende doch einfach ein Interface ala so:class TimerCallback { public: virtual ~TimerCallback() {} virtual void OnTick() = 0; // braucht keine parameter! }; void Foo::CreateTimer(double delay, TimerCallback* callback) { // ... } void Foo::OnTick() { // ... callback->OnTick(); delete callback; // löscht callback inklusive aller parameter // ... } // Benutzung: class MyTimerCallback : public TimerCallback { public: MyTimerCallback(int a, int b, int c) : m_a(a), m_b(b), m_c(c) { } virtual void OnTick() { printf("%d, %d, %d\n", m_a, m_b, m_c); } private: int m_a; int m_b; int m_c; }; void Test() { MyTimerCallback* callback = new MyTimerCallback(1, 2, 3); foo->CreateTimer(42, callback); }Oder verwende gleich boost::function statt
TimerCallback.
-
Ich muss schon sagen: Die Idee ist genial!
Danke
Gruß