Probleme mit std::list
-
Hi,
ich versuche eine Liste (std::list) zu erstellen und dann auf die Elemente zuzugreifen. Das ganze sieht so aus das ich eine std::list von "ScrollableList"-Objekten habe (wobei hier der name verwirrend ist, "ScrollableList" ist keine Liste sondern einfach jetzt irgend eine Klasse) die die Methode set_active_element(int i) haben. Es wär jetzt zu lang, und vor allem irrelevant was diese Methode macht, wichtig ist einfach nur dass ich später sehen kann welche Zahlen alle damit in dem "ScrollableList"-Objekt auf dem das aufgerufen wird, gesetzt wurden.
Also, ich erstelle also ein "ScrollableList"-Objekt und rufe darauf die Methode set_active_element(1) auf, dann füge ich dieses "ScrollableList"-Objekt einer std::list hinzu, und rufe dann nochmal über die Liste die Methode i]set_active_element(2)[/i] auf. Ich mache aber irgendwas falsch, denn wenn ich mir dann angucke welche Zahlen gesetzt wurden, wurde nur die 1 gesetzt.
Code:
std::list<ScrollableList> menu_list; ScrollableList *neueliste = new ScrollableList(); neueliste->set_active_element(1); menu_list.push_back(*neueliste); menu_list.front().set_active_element(2);
Was mach ich da falsch?
Grüße
Lukas
-
Du Speicherst eine Kopie in der Liste, keine Referenz auf das Orginal.
-
Dann kommt noch dazu, dass du hinten einfügst, aber immer vorne einen Iterator holst und dieses Objekt veränderst. (versuch das mal mit back() zu machen).
-
Das ist aber in diesem Beispiel so ziemlich egal!
-
David_pb schrieb:
Du Speicherst eine Kopie in der Liste, keine Referenz auf das Orginal.
Das will ich auch, denn, ich habe den Code hier zusammengefügt, die *ScrollableList neueliste wird in einer Methode von "MainMenu" erstellt. std::list<ScrollableList> menu_list; ist eine Variable von "MainMenu". Würde ich nur die Referenz speichern würde er die tatsächichen Daten doch löschen und die Referenz ginge ins leere (?).
MainMenu.h:
class MainMenu { private: static std::list<ScrollableList> menu_list; // [...] public: void add_menu(); // [...] };
MainMenu.cpp:
void MainMenu::add_menu() { ScrollableList *neueliste = new ScrollableList(); // [...] neueliste->set_active_element(0); this->menu_list.push_back(*neueliste); menu_list.front().set_active_element(2); }
drakon schrieb:
Dann kommt noch dazu, dass du hinten einfügst, aber immer vorne einen Iterator holst und dieses Objekt veränderst. (versuch das mal mit back() zu machen).
Krasserweise funktiert das dann. Sollte front() nicht das erste Element holen und nicht den iterator? Hier ist das auch so: http://www.cplusplus.com/reference/stl/list/front.html
-
frage die hier war passt nicht zum thema -> neuer thread: http://www.c-plusplus.net/forum/viewtopic-var-p-is-1643924.html#1643924
-
David_pb schrieb:
Das ist aber in diesem Beispiel so ziemlich egal!
Ich hoffe mal nicht, dass er eine Liste nur für einen Eintrag nutzt.
Krasserweise funktiert das dann. Sollte front() nicht das erste Element holen und nicht den iterator? Hier ist das auch so:
Stimmt. Hatte begin() im Kopf.
Das will ich auch, denn, ich habe den Code hier zusammengefügt, die ScrollableList *neueliste wird in einer Methode von "MainMenu" erstellt. std::list<ScrollableList> menu_list; ist eine Variable von "MainMenu". Würde ich nur die Referenz speichern würde er die tatsächichen Daten doch löschen und die Referenz ginge ins leere (?).
Du forderst den Speicher per new an. Das heisst, dass der Speicher erst freigegeben wird, wenn du ihn per delete freigibst.
Wenn du eine Liste mit Objekten (und keine Zeiger auf Objekte) hast, dann kannst du bei der Erstellung auch ein auto-Objekte haben. (Also ohne new). Das wird dann einfach per Kopier eingefügt und du musst dich um die Freigabe nicht mehr kümmern, da das Objekt freigegeben wird, wenn es aus der Liste entfernt wird. (erase, oder dtor der Liste).Ansonsten musst bei Listen aufpassen, dass sie auch etwas enthalten.
-
drakon schrieb:
David_pb schrieb:
Das ist aber in diesem Beispiel so ziemlich egal!
Du forderst den Speicher per new an. Das heisst, dass der Speicher erst freigegeben wird, wenn du ihn per delete freigibst.
Wenn du eine Liste mit Objekten (und keine Zeiger auf Objekte) hast, dann kannst du bei der Erstellung auch ein auto-Objekte haben. (Also ohne new). Das wird dann einfach per Kopier eingefügt und du musst dich um die Freigabe nicht mehr kümmern, da das Objekt freigegeben wird, wenn es aus der Liste entfernt wird. (erase, oder dtor der Liste).Ansonsten musst bei Listen aufpassen, dass sie auch etwas enthalten.
Ah ja, vielen Dank. Nur den letzten Satz versteh ich nicht ganz. Heisst das einfach dass ich nicht auf listen mit front() und so zugreifen sollte wo nix drin ist weil's sonst Rabauz gibt?
-
Du musst nur den Fall bedenken, was passiert, wenn die Liste leer ist.
-
drakon schrieb:
David_pb schrieb:
Das ist aber in diesem Beispiel so ziemlich egal!
Wenn du eine Liste mit Objekten (und keine Zeiger auf Objekte) hast, dann kannst du bei der Erstellung auch ein auto-Objekte haben. (Also ohne new). Das wird dann einfach per Kopier eingefügt und du musst dich um die Freigabe nicht mehr kümmern, da das Objekt freigegeben wird, wenn es aus der Liste entfernt wird. (erase, oder dtor der Liste).
Ich such grad danach wie das funktioniert, finde aber nichts. Kannst du mal n paar Sichworte sagen wonach man da suchen sollte?
-
Das sind die Grundlagen von C++. Kopieren, Zeiger, new, delete usw.
std::list<int> v; v.push_back ( 1 ); // wird per kopie eingefügt std::list<int*> v2; v.push_back ( new int ( 2 ) ); // hier wird nur der Zeiger gespeichert und nicht das eigl. Objekt int.
Den ersten Container kannst du einfach so stehen lassen beim beenden. Die Objekte werden automatisch zerstört, wenn der Container zerstört wird.
Den zweiten Container musst du noch von Hand freigeben:for (std::list<int*>::iterator it = v2.begin(); it != v2.end();) { delete (*it); //explizite freigabe des angeforderten Speichers it = v2.erase ( it ); }
-
Ok, danke, da ist es auch in der Tat viel sinnvoller wirklich Objekte einzufügen als den new-Kram zu machen. Jetzt hab ich aber beim pushen eines Objektes in die Liste ein Problem, er stürzt ab.
MainMenu.h:
class MainMenu { private: std::list<ScrollableList> menu_list; // [...] public: void add_menu(); // [...] };
MainMenu.cpp:
void MainMenu::add_menu() { ScrollableListElement elementenliste[10]; for(int i=0; i<10; i++) { elementenliste[i] = ScrollableListElement("Element"); } this->menu_list.push_back(ScrollableList(elementenliste, 9)); // Hier stürzt er ab. }
Wenn ich einfach ein ScrollableList-Objekt erzeuge mit dem Konstruktor stürtz er nicht ab, scheint also wirklich am pushen zu liegen...
-
Was bedeutet, das es an deinem Copykonstruktor liegt da das erzeugte Objekt ja in den Container kopiert wird.
-
Braunstein schrieb:
Was bedeutet, das es an deinem Copykonstruktor liegt da das erzeugte Objekt ja in den Container kopiert wird.
Genau. Was heisst, dass, wenn die Klasse etwas nicht-triviales enthält, also irgendetwas verwalten muss (wie z.B Speicher oder andere Resourcen), dann musst du dir den Kopierkonstruktor selbst schreiben. (copy/swap wäre hier das Stichwort).
-
Ah, ok, macht auch sinn, da drin ist n pointer, der zeigt dann wohl in den Urwald. Und bitte steinigt mich nicht für meine weitere Nooberei, ich hab probleme beim kopieren des Inhalts vom Pointer. Der ist nämlich dafür da um auf ein Array zu zeigen:
class ScrollableList { private: ScrollableListElement *list_elements; int num_list_elements; // [...] public: ScrollableList(ScrollableListElement list[], int length); ScrollableList(const ScrollableList &sl); // Operator kommt noch };
ScrollableList::ScrollableList(ScrollableListElement list[], int length) { this->list_elements = list; this->num_list_elements = length; }
Wie kopier ich dann den Inhalt davon? Muss ich da tatsächöich durchgehen und jedes Element kopieren oder gibt es da ne schönere, einfacherere Variante mit dereferenzierung und kopieren des Inhalts?
-
Luke-2 schrieb:
Wie kopier ich dann den Inhalt davon? Muss ich da tatsächöich durchgehen und jedes Element kopieren oder gibt es da ne schönere, einfacherere Variante mit dereferenzierung und kopieren des Inhalts?
Ja. Da musst du alles durchgehen. Du kannst auch einen Standard Container nehmen, allerdings musst auch der bei einer Kopie innerhalb durch alle Elemente gehen.
Die wohl sicherste Weise eine solche Klasse zu kopieren wäre hier einen vernünftigen Kopierkonstruktor zu schreiben, wo du jedes Element kopierst, respektive die Grösse des Arrays der anderen Instanz abfrägst und dann per new auch wieder Speicher holst.