Vectoren in Liste speichern



  • Ich hab das so realisieren wollen:
    Das zu speichernde Objekt wird auf dem Heap angelegt.
    Der dereferenzierte Zeiger wird in der Liste gespeichert, also das Objekt als
    Wert.
    Der Speicher des Objekts wird freigegeben.
    Dann wiederholt sich das ganze für das nächste Objekt.

    Muss ich dann trotzdem einen Kopierkonstuktor schreiben?



  • Warum kompliziert wenn´s auch einfach geht?

    Du willst das so machen:

    // A sei eine Klasse
    vector< A > v;
    A* pA = new A();
    v.push_back(*pA)
    delete pA;
    

    Warum geht es nicht so:

    v.push_back(A());
    

    ?

    // edit:
    Zur Frage: Ja. Ein dereferenzierter Pointer ist das Objekt selbst. Also brauchst du einen Copy-Constructor. Allerdings musst du den nur selbst schreiben wenn du mit dynmaischem Speicher in der Klasse arbeitest.

    Gruß
    Don06



  • Nee, anders:

    Das zu speichernde Objekt enhält 2 Strings und einen Vector von Strings.
    Die Grösse des Vectors wird erst zur Laufzeit ermittelt, bleibt aber dann
    für alle Objekte gleich.
    Das Hauptprogramm ruft eine Funktion auf, die ein solches Objekt auf dem
    Heap erzeugt, und einen Zeiger auf das Objekt zurückgibt.
    Das Hauptprogramm dereferenziert den Zeiger und Speichert das Objekt als
    Wert in der Liste. Dann löscht das Hauptprogramm den Zeiger.
    Dann ruft das Hauptprogramm die Funktion erneut auf, und es folgt das
    nächste Objekt.

    int main()
    {
    int NumberOfEntries = 0;
    list<cConfigEntry>* Configuration = new list<cConfigEntry>;
    
    cConfigEntry *ConfigEntry = FindEntries(TempLine);
    
    Configuration->push_back(*ConfigEntry);
    NumberOfEntries++;
    delete ConfigEntry;
    }
    

    cConfigEntry ist die Klasse, von der Objekte gespeichert werden sollen.
    Die Funktion cConfigEntry::FindEntries liefert den Zeiger auf das Objekt.
    In der Liste ConfigEntry soll das Objekt nun gespeichert werden.
    NumberOfEntries soll die Anzahl der Einträge zählen.
    Danach wird das Objekt gelöscht.

    Ich hab das ganze jetzt nur mal in ein Hauptprogramm gepackt.
    Eigentlich ist es eine weitere Klasse, die ein File ausliest, bis eof
    erreicht ist. Jede Zeile wird an das dynamische Objekt aus cConfigEntry
    übergeben.
    In der Klasse cConfigEntry wird das Objekt anhand der übergebenen Zeile
    zusammengebaut.
    Das sind 2 Strings und ein String-Vector.



  • Nur das Objekt selber ist dynamisch.
    Die beiden Strings und der Vector nicht.



  • Wenn in cConfigEntry nur std::string, std::vector und POD (also int, double, ...) als Daten verwendest, brauchst du keinen Copy-Constructor schreiben. Dann reicht auch der vom Kompiler aus.

    Aber was funktioniert an deiner Lösung denn jetzt nicht?

    // edit: warum ist die list dynmaisch angelegt?

    Gruß
    Don06



  • Ich bekomme die Warnung, dass die Variable Configuration nicht verwendet
    wird. Ich hab sie als privaten Member der Klasse deklariert.
    Also so im privaten Abschnitt der Klasse:

    std::list<cConfigEntry>* Configuration;
    

    und dann so im Konstruktor implementiert:

    cConfigFile::cConfigFile(FType _FileType, string _FilePath, unsigned _NumberOfValues, string _Separator) : FileType(_FileType), FilePath(_FilePath), NumberOfValues(_NumberOfValues), Separator(_Separator)
    {
    	list<cConfigEntry>* Configuration = new list<cConfigEntry>;
    }
    

    Der Standardkonstruktor ist leer und privat, da eine Parameterübergabe
    erfolgen muss.
    Zuerst erhalte ich o. g. Warnung, aber

    Configuration->push_back(*ConfigEntry);
    

    in einer Klassenmethode liefert keinen Fehler.
    Und auch das

    delete Configuration;
    

    im Destruktor liefert keinen Fehler.
    Die Liste will ich dynamisch anlegen, weil sie unter Umständen einige
    hundert Objekte speichern muss.



  • Ich glaub, du hast da was falsch verstanden. Das list-Objekt speicherst du auf dem Stack, die dynamische Speicherung der Objekte übernimmt die Liste für dich.

    Sehr kompliziert machst du das alles...



  • Gut, also jetzt mal kurz ne Info:

    std::list speichert seine Daten auf dem Heap. Nur ein kleiner Teil von std::list ist auf dem Stack. Die Größe dieses Teils müsstest du mit dem sizeof()-Operator ermitteln können. (eben überprüft: bei mir sind das 24 Byte)
    Es ist also egal wie viele Elemente du anlegst, auf dem Stack bleibt die Größe des Objekts konstant.

    und hier:

    {
        list<cConfigEntry>* Configuration = new list<cConfigEntry>;
    }
    

    legst du einen temporären Pointer an, forderst neuen Speicher an und am Ende des Konstruktors wird der Pointer gelöscht -> Speicherleck

    So müsste es heißen:

    {
        Configuration = new list<cConfigEntry>;
    }
    

    Achja, der Sinn von Container-Klassen(vector, list, deque, ...) ist es die Speicherverwaltung (new, delete) zu kapseln. Der Anwender muss sich um solche Dinge nicht mehr kümmern.

    Deshalb scheint deine Benutzung dieser Klassen wenig sinnvoll.

    Gruß
    Don06



  • Danke euch!
    Mit der Liste auf dem Stack geht's jetzt!



  • HumeSikkins schrieb:

    Deine Objekte müssen lediglich die "Assignable"-Eigenschaft erfüllen, konkret für list bedeutet dass, das sie kopierbar sein müssen.

    Heißt die "Assignable"-Eigenschaft immer, dass Sie kopierbar sein müssen?

    Viele Grüße,
    Assignable



  • Assignable schrieb:

    HumeSikkins schrieb:

    Deine Objekte müssen lediglich die "Assignable"-Eigenschaft erfüllen, konkret für list bedeutet dass, das sie kopierbar sein müssen.

    Heißt die "Assignable"-Eigenschaft immer, dass Sie kopierbar sein müssen?

    Grundsätzlich heißt das, dass Objekte kopier- und zuweisbar sein müssen. Zuweisungen werden aber nur unter bestimmten nötig, deshalb kommt man häufig auch ohne diese Eigenschaft davon.


Anmelden zum Antworten