Template Ringbuffer



  • Hallo!

    Ich brauche in meinem Projekt einen generischen "Ringbuffer". Damit meine ich folgendes: Zur Compilezeit ist die größe und der Typ klar, man legt ihn also so an:

    Ringbuffer<int, 5> foo;
    

    foo kann also jetzt 5 ints aufnehmen. Wenn ich das 6. Element hinzufüge, dann wird das 1. Element überschrieben. Das 7. Element überschreibt das 2. usw. Ich kann also unendlich viele Elemente hinzufügen, ingesamt speichert er aber immer nur eine fixe Anzahl und die ältesten Elemente werden überschrieben.

    Mein Problem:
    Wenn der Buffer voll ist, werden ja die ältesten Daten überschrieben. Bei primitiven Typen wie int, float is das kein Problem. Mein Problem ist jedoch, dass ich auch Zeiger speichern werde und zwar auf Objekte auf dem Heap. Also sowas:

    Ringbuffer<int*, 2> foo2;
    foo2.push( new int(3) );
    foo2.push( new int(11) );
    foo2.push( new int(20) );
    

    Hier hätte ich nun ein Speicherleck erzeugt, da der Buffer ja nur 2 Elemente speichern kann und das 3. Element das 1. Element überschreiben würde. Den Speicher von new int(3) kann ich also nie mehr freigeben.

    Wie designe ich den Buffer so, dass er auch mit Heap alloziierten Speicher klarkommt?



  • ringbufferschreiber schrieb:

    Wie designe ich den Buffer so, dass er auch mit Heap alloziierten Speicher klarkommt?

    Das macht die andere Klasse

    PtrRingbuffer<int, 5> foo;
    
    void push(T* ptr){
       delete data[writePos];
       data[writePos]=ptr;
    }
    


  • Danke für die schnelle Antwort 👍

    Ok verstehe, du rätst mir also 2 Klassen anzulegen. Die Idee hatte ich auch schon, wusste aber nicht, ob das in C++ gut ist.
    Man kann doch irgendwie auch Templates spezialisieren. Würde das in meinem Fall gehen? Also das ich einen Ringbuffer für Typ T habe (alle nicht-pointer) und für T* eine Spezialisierung.



  • ringbufferschreiber schrieb:

    Danke für die schnelle Antwort 👍

    Ok verstehe, du rätst mir also 2 Klassen anzulegen. Die Idee hatte ich auch schon, wusste aber nicht, ob das in C++ gut ist.
    Man kann doch irgendwie auch Templates spezialisieren. Würde das in meinem Fall gehen? Also das ich einen Ringbuffer für Typ T habe (alle nicht-pointer) und für T* eine Spezialisierung.

    Nö! Ptr... ist ein Container, der delete ausführt.
    Kannst einen RingBuffer<int*> machen, der macht kein delete, um Zeiger in ein fremdes Array zu halten. Und ein PtrRingBuffer<int> (oder PtrRingBuffer<int*>, ka, wie Du das haben willst) löscht eben bei Bedarf, aber ein Zeiger in ein fremdes Array darf ja nicht mit delete gelöscht werden.


Anmelden zum Antworten