malloc und free -> Constructor und Destructor



  • Hi leute, ich arbeite momentan mit einem C interface (python) auf wessen Grundlage ich eine umfangreiche reflection lib für C++ programmiert habe.
    Da hier allerdings nur der erforderliche speicherplatz mit malloc reserviert wurde, aber nicht der Constructor aufgerufen wurde muss ich das dann noch selber machen.

    Ich habe momentan leider keine möglichkeit das ganze zu testen, deshalb wollte ich mir hier rat suchen. Würde folgendes korrekt funktionieren:

    #include <cstdlib>
    using namespace std;
    
    class Sample
    {
    private:
        unsigned int m_Irgendwas; // ein bisschen speicher sollte schon reserviert werden
    public:
        Sample( )     { }
        ~Sample( )    { }  
    };
    
    int main( )
    {
        Sample* MySample = (Sample*)malloc( sizeof(Sample) );
        MySample->Sample( ); // sollte den constructor aufrufen
        // äquivalent zu Sample* MySample = new Sample();
    
        MySample->~Sample( );
        free( MySample );
        // äquivalent zu delete MySample;
    }
    

    ?



  • Der Destruktor wird zum Schluss automatisch aufgerufen. Und warum verwendest du nicht new und delete? Wäre zumindest nicht so ein Mix aus C und C++...



  • Placement New und manueller Destruktoraufruf sind deine Freunde.

    T* ptr = static_cast<T*>( malloc(sizeof(T)) ); // Allokation
    new (ptr) T(args);                             // Konstruktion
    
    ptr->~T();                                     // Zerstörung
    free(ptr);                                     // Deallokation
    

    Langi schrieb:

    Der Destruktor wird zum Schluss automatisch aufgerufen.

    Falsch. Dies trifft nur auf automatische Variablen zu.



  • der constructor kann also nur mit

    new(MySample) Sample();
    

    aufgerufen werden?

    Warum geht nicht einfach ein MySample->Sample() (wenn ja MySample->~Sample() geht)?



  • Krauzi schrieb:

    Warum geht nicht einfach ein MySample->Sample() (wenn ja MySample->~Sample() geht)?

    Naja ... das ist nunmal einfach so ... Konstruktoren und Destruktoren sind "namenlos". MySample->Sample() sieht dagegen nach einem "normalen" Funktionsaufruf aussieht.

    class foo {};
    typedef foo bar;
    
    int main()
    {
      bar *p = (bar*)mallox(sizeof(bar));
      p->foo();  oder  p->bar(); ???
    }
    

    Richtig sieht es nunmal so aus:

    #include <new>
    :
    bar *p, *q;
    :
    new (p) bar(); // dies, aber
    new (q) foo(); // das geht auch
    


  • krümelkacker schrieb:

    Richtig sieht es nunmal so aus:

    #include <new>
    :
    bar *p, *q;
    :
    new (p) bar(); // dies, aber
    new (q) foo(); // das geht auch
    

    Vielleicht, damit Kauzi nicht verwirrt wird: Hier ist aber der Teil dazwischen entscheidend. Wenn das Argument für Placement New (die Adresse, an der das Objekt konstruiert wird) ein uninitialisierter Zeiger ist, wird undefiniertes Verhalten hervorgerufen.

    krümelkacker schrieb:

    p->foo();  oder  p->bar(); ???
    

    Naja, beim Destruktor kann man schliesslich ebenfalls sowohl p->~foo() als auch p->~bar() schreiben. Aber es ist natürlich wegen des "~" eindeutig, da hast du Recht.

    Merkwürdig finde ich aber, dass Folgendes unter MSVC++ keine Compilerfehlermeldung erzeugt und sogar zu funktionieren scheint (nicht benutzen, das ist kein gültiges C++):

    p->foo::foo(); // explizite Konstruktion
    

Log in to reply