Klassenpointer zu void* mit anschließendem delete



  • Hi leute, ich muss wegen einer funktion wegen threading einen klassen pointer (kann zur not auch eine strukture machen, wenn das ganze damit besser bzw. schneller läuft) in einen void pointer wandeln.
    Ich dachte daran an einen simplen cast mittels (void 😉 (ja ich mag den c-style lieber 🙂 ).
    Folgendes bsp. soll das ganze erläutern:

    ...
        MeineKlasse *ptr = new MeineKlasse("arg1", "arg2") /* "arg2" ist in wirklichkeit eine Struktur */
        MeineFunktionDieEinenVoidPtrBraucht(MeineFunktion, (void *)ptr);
    }
    
    void MeineFunktion(void *MeineKlasseAlsVoidPtr) {
        MeineKlasse *ptr = (MeineKlasse *)MeineKlasseAlsVoidPtr;
        ... /* ptr wird benutzt und sonstige funktionen werden aufgerufen *
             * Das ganze läuft übrigens Threaded ab                       *
             * (wegen Funktion "MeineFunktionDieEinenVoidPtrBraucht"      */
        delete ptr;
    }
    

    Meine Fragen:
    1.) Gibt es eine elegantere methode das ganze zu casten?
    2.) Wird das 'delete ptr' ordentlich funktionieren, also das "rückcasten" so funktionieren, dass dannach keine Speicherlöcher entstehen?

    MfG Krauzi.



  • Das ist eine relative häufig verwendete Methode bei C Callback funktionen. z.B. in der WinAPI, (oder war früher auch so bei SQLite2.x), uvm

    er erste cast

    MeineFunktionDieEinenVoidPtrBraucht(MeineFunktion, (void *)ptr);
    

    sollte unnötig sein wenn sie einen void Zeiger erwartet.

    Ansonsten bleibt dir da nicht viel anderes übrig als das so oder zumindest so ähnlich umzusetzen.



  • Krauzi schrieb:

    1.) Gibt es eine elegantere methode das ganze zu casten?

    Ja, gar nicht, T* -> void* geht implizit. Aber grundsätzlich sind die C++-Cast-Operatoren eleganter, weil typsicherer.

    Krauzi schrieb:

    2.) Wird das 'delete ptr' ordentlich funktionieren, also das "rückcasten" so funktionieren, dass dannach keine Speicherlöcher entstehen?

    Sofern der Originaltyp derselbe ist, ja.

    Aber es ist unschön, wenn die Funktion sich um die Speicherfreigabe kümmern muss. Warum macht das nicht der Aufrufer, der den Speicher auch angefordert hat?

    Krauzi schrieb:

    klassen pointer (kann zur not auch eine strukture machen, wenn das ganze damit besser bzw. schneller läuft)

    Die Änderung des Schlüsselworts hat keinen Einfluss auf die Performance. Bei modernen Compilern hat dies nicht einmal der Umstand, ob Funktionen statt direktem Memberzugriff verwendet werden.



  • Aber es ist unschön, wenn die Funktion sich um die Speicherfreigabe kümmern muss. Warum macht das nicht der Aufrufer, der den Speicher auch angefordert hat?

    Es gibt Fälle, wo es nicht anders geht, bzw. einfach Sinn macht.
    z.B. wenn man einen Thread startet, dem man eine kleine "was soll ich eigentlich machen" Struktur mitgibt.
    Damit dieser "detached" laufen kann, muss er die "Ownership" der Struktur übernehmen, und damit muss er sich auch freigeben.
    Und meist ist es ausreichend da dann einen (evtl. virtuellen) Destruktor mittels delete aufzurufen. Man kann zu dem Zweck aber natürlich auch eine spezielle (virtuelle) "lösch mich" Funktion bauen. Bringt aber nur was, wenn man es u.U. mit Strukturen zu tun hat, die nicht über den globalen Operator delete entsorgt werden sollten (placement new, Pools, ...).


Log in to reply