Suche: Alternative zu realloc() in C++



  • Zitat aus einem Tutorial:
    "Mit new ist es nicht möglich, ein bereits allokiertes Feld im Nachhinein in der Größe zu verändern, so wie es realloc() kann."

    Frage:
    Wie veränder ich dann den von new allokierten Speicherplatz in C++?



  • größeren Bereich reservieren, Werte kopieren, alten Bereich freigeben.

    (oder du nutzt einen STL-Container und freust dich darüber, daß der die Speicherverwaltung selber übernimmt)



  • Ich hatte eigentlich gedacht das mir sowas erspart bliebe.
    Ich finde das sehr umständlich, aber wenns nicht anders geht mach ich das so.

    Wie siehts aber da mit der Rechenzeit aus?
    Was ist schneller um speicher zu vergrößern?
    a) Größeren Speicher reservieren, kopieren, alten freigeben
    b) realloc()
    Wie arbeitet realloc intern? (dassselbe->reservieren, kopieren, alten freigeben o. reserviert realloc nur denn neu benötigten speicher neu solange noch platz hinter dem alten speicherblock ist?)

    Verlieree ich also bei dieser methode viel rechenzeit oder ist es dasselbe wie realloc nur umständlich geschrieben?



  • Das nimmt dir später wie gesagt alles die STL ab, da gibts für (fast) jeden Zweck was.

    std::list (schnelles einfügen / löschen / verschieben + bissl overhead)
    std::vector (gut wenn sich die größe nur selten ändert und sich die Datenmengen in Grenzen halten)

    War natürlich nicht alles, wie gesagt nach STL suchen.

    Übrigens macht das realloc genau gleich (neuer Speicher, kopiere, alter weg), in C++ geht das imo net so einfach weil ein "C++ realloc" nicht wissen würde wie es Objekte zu kopieren hat.



  • Das muß realloc auch garnicht wissen. Es kennt die Größe des alten und des neuen Bereiches, kann somit die Daten einfach bitweise kopieren. Wenn noch Platz hinter dem alten Speicherblock ist, wird erweitert.
    Das für den neuen Speicherblock keine Konstruktoren aufgerufen werden steht auf einen anderen Blatt.



  • Braunstein schrieb:

    Das muß realloc auch garnicht wissen. Es kennt die Größe des alten und des neuen Bereiches, kann somit die Daten einfach bitweise kopieren.

    Ja, für C-Strukturen reicht diese bitweise Kopie auch völlig aus - aber Objekte in C++ sind idR etwas komplexer.

    Das für den neuen Speicherblock keine Konstruktoren aufgerufen werden steht auf einen anderen Blatt.

    Aber das dürfte der Grund sein, daß realloc() nicht mit new kompatibel ist 😉 (neue Objekte benötigen zumindest den Aufruf des Default-Konstruktors und überhängende Objekte müssen ordentlich beseitigt werden (wenn der neue Bereich kleiner wird)

    PS: Die schnellste Version ist es übrigens, gleich am Anfang genügend Speicher zu beschaffen 😉



  • Das realloc nicht mit new kompatibel ist, ist ja klar. Ich sollte vielleicht noch dazu sagen, dass ich realloc weder verwende noch für seine Verwendung plädiere.
    Warum eine bitweise Kopie nicht geht, ist mir aber nicht ganz klar. Klar sind C++-Objekte kompliezierter, aber letztlich auch nur eine Folge von Bits. Es werden doch auch schließlich alle Pointer mitkopiert (einschließlich dem auf die VTable wenn vorhanden). Der Speicherbereich auf den die Pointer zeigen wird ja nicht angefasst. Mir fällt im Augenblick kein Argument ein warum das nicht gehen soll.



  • Das Problem dabei sind nicht die Elemente, die kopiert wurden, sondern die, die NICHT kopiert wurden. Für neue Objekte muß der Default-Konstruktor aufgerufen werden, für gelöschte Elemente der Destruktor (andernfalls erhältst du Datenmüll bzw. ein breites Speicherleck).



  • Braunstein schrieb:

    Warum eine bitweise Kopie nicht geht, ist mir aber nicht ganz klar. Klar sind C++-Objekte kompliezierter, aber letztlich auch nur eine Folge von Bits. Es werden doch auch schließlich alle Pointer mitkopiert (einschließlich dem auf die VTable wenn vorhanden). Der Speicherbereich auf den die Pointer zeigen wird ja nicht angefasst. Mir fällt im Augenblick kein Argument ein warum das nicht gehen soll.

    Hallo Braunstein,

    es werden aber nicht die Pointer aktualisiert, die auf das Objekt oder Teile davon zeigen. Stell Dir nur mal eine String-Implementierung vor, die solche Member hat:

    class String
    {
        // ...
    private:
        char* m_pData;      // zeigt auf String-Daten
        char m_data[10];    // Speicher für kleine Strings
        std::size_t m_len;  // String-Länge
        std::size_t m_cap;  // Größe des allokierten Speichers
    };
    

    Für kleine Strings bis 10(oder 9) Zeichen läßt der Implementierer der String-Klasse den Member m_pData auf m_data zeigen. Copy-Konstruktor, Assingment-Operator und Destruktor nehmen selbstverständlich darauf Rücksicht. Aber was tun, wenn dieses Ding in einen Container lebt, dessen Allocator ein realloc durchführt beim dem ein Objekt im Speicher verschoben wird?

    Darüber hinaus meine ich, dass es in C++ definiert ist, dass diese Abfrage

    T* p = ...;
        if( p == this ) // Identität feststellen; *this ist vom Typ T oder Derivat
    

    immer korrekt funktioniert. Das würde ein realloc auch verhindern.

    Gruß
    Werner



  • Ok, Ihr habt mich überzeugt.
    Danke.


Log in to reply