list iterator not derefencable
-
folgende klassenstruktur:
owner ist ein teil von flat, flat ist ein teil von floor, floor ist ein teil von house,...class House: public Object { public: House(); virtual ~House(); virtual void Print(std::ostream&out) const; TAddress GetAddress() const; void SetAddress(TAddress const & address); size_t GetNrFloors() const; void AddFloor(const Floor & flobj); House& operator =(House const & cfloor); House (const House & cFloor); private: TAddress mAddress; TFloorList mFLoors; size_t mNrFloors; }; typedef std::list<Floor> TFloorList; typedef TFloorList::const_iterator TFloorListItor;House::House(const House & cFloor) { mNrFloors=cFloor.mNrFloors; mAddress=cFloor.mAddress; copy ( cFloor.mFLoors.begin(),cFloor.mFLoors.end(), mFLoors.begin() ); }class Flat; //typedefs for list of flats and iterator for flat list typedef std::list<Flat> TFlatList; typedef TFlatList::const_iterator TFlatListItor; class Floor: public Object { public: size_t GetNrFlat() const; virtual void Print(std::ostream & out) const; void SetNrFlat(size_t const & nrFlat); Floor& operator =(Floor const & c); Floor (const Floor & cFloor); Floor(); virtual ~Floor(); void AddFlat(Flat const &flat); private: size_t mNrFlat; TFlatList mFlatList; };
-
Vollständiges Minimalbeispiel heißt, man kann den Code einfach per Copy&Paste in seine IDE hauen, durchcompilieren und selber testen. Dazu musst Du die Dateien zu einer zusammenführen und Sachen wegmachen, die irrelevant sind.
-
also gut versuch zwei:
class house:
typedef std::list<Floor> TFloorList; typedef TFloorList::const_iterator TFloorListItor; class House { public: void AddFloor(const Floor & flobj); House& operator =(House const & cfloor); House (const House & cFloor); private: TFloorList mFLoors; }; House& House::operator =(House const & cfloor) { //check for self-assignment if(this!=&cfloor) { copy (cfloor.mFLoors.begin(),cfloor.mFLoors.end(), mFLoors.begin() ); } return *this; } House::House(const House & cFloor) { copy ( cFloor.mFLoors.begin(),cFloor.mFLoors.end(), mFLoors.begin() ); } void House::AddFloor(const Floor & flobj) { mFLoors.push_back(flobj); }typedef std::list<Flat> TFlatList; typedef TFlatList::const_iterator TFlatListItor; class Floor { public: size_t GetNrFlat() const; Floor& operator =(Floor const & c); Floor (const Floor & cFloor); Floor(); virtual ~Floor(); void AddFlat(Flat const &flat); private: size_t mNrFlat; TFlatList mFlatList; };Floor::Floor(const Floor & cFloor) { mNrFlat=cFloor.mNrFlat; copy (cFloor.mFlatList.begin(),cFloor.mFlatList.end(),mFlatList.begin()); Floor& Floor::operator =(const Floor & c ) { if(this!=&c) { mNrFlat=c.mNrFlat; copy ( c.mFlatList.begin(),c.mFlatList.end(),mFlatList.begin()); } return *this; } void Floor::AddFlat(Flat const & flat) { mFlatList.push_back(flat); } }klasse flat:
// typedefinition for owner typedef Owner TOwner; class Flat // { public: // Constructor with default values : Flat( size_t const& size = 0, TOwner const& name = Owner()); // Copy-constructor Flat(Flat const & fl_cc); // Set owner void SetOwner(TOwner const& name); // Assignment operator overloading Flat & operator=(Flat const & fl); // Members private: // Size of flat size_t mSize; // Flat owner (if any) TOwner mOwner; }; // Constructor Flat::Flat(size_t const& size , TOwner const& name ) : mSize(size) , mOwner(name) {} // Copy-constructor Flat::Flat(Flat const & fl_cc) { mSize = fl_cc.mSize; mOwner = fl_cc.mOwner; } // Assignment operator overloading Flat & Flat::operator=(Flat const & fl) { (*this).mOwner = fl.mOwner; (*this).mSize = fl.mSize; return (*this); }class owner:
class Owner { public: // Constructor : if certain data is introduced, it will be automatically introduced by default Owner(std::string const & fn="FIRST_NAME_Pending",std::string const & ln="LAST_NAME_Pending",size_t const & yob=0); // Members: private: // Last name of owner std::string mLastName; // First name of owner std::string mFirstName; // Year of birth of owner std::size_t mYearOfBirth; }; // Constructor : if certain data is introduced, it will be automatically introduced by default Owner::Owner(string const & fn,string const & ln,size_t const & yob) : mFirstName(fn), mLastName(ln), mYearOfBirth(yob) {}
-
Das ist mir nicht minimal genug. Habe jetzt nur den ersten Fetzen überflogen. Das hat mir schon gereicht! So kopiert man keine Listen! Wenn du std::copy so verwenden willst bräuchtest du einen
back_inserterals Output-Iterator. Aber das ist eh Quatsch in diesem Fall. House hätte so aussehen sollen:class House { public: void AddFloor(const Floor& flobj); private: std::list<Floor> mFLoors; }; void House::AddFloor(const Floor& flobj) { mFLoors.push_back(flobj); }und gut ist! Die vom Compiler automatisch generierten Kopieroperationen für House tun schon genau das, was du willst.
Ob std::list wirklich das ist, was du brauchst, müsstest du auch nochmal überlegen. Dir ist klar, dass die Liste die Objekte bei push_back kopiert, ja? Das übergebene flobj und das, was dann in der Liste landet sind nicht dieselben Objekte (im Sinne der Objektindentität). Ich sag's nur, weil du hier und da auch noch mit Zeigern rumhantierst.
Ein Minimalbeispiel besteht nicht aus 5 einzelnen Dateien und ist auch nicht so lang. Das will doch keiner lesen.
-
ACnut schrieb:
kriege die oben genannte abort assertion error und wenn ich auf ignorieren drücke, dann steht standard c++ libraries out of range.
Dann hast du Glück. Sieht so aus, als ob Du die Standardbibliothek in einem Modus betreibst, wo zusätzliche Überprüfungen gemacht werden, die nicht vom C++ Standard her vorgeschrieben sind. MSVC und GCC bieten das jedenfalls an und ich kann es nur jedem empfehlen, einen solchen Debug-Modus während der Entwicklung zu verwenden.
Das dazu passende Minimalbeispiel sieht bestimmt so aus:
#include <list> #include <algorithm> int main() { std::list<int> a; std::list<int> b; a.push_back(42); std::copy(a.begin(),a.end(),b.begin()); // <-- Hier ist Dein Bug }Und hier ist die Lösung:
#include <list> int main() { std::list<int> a; std::list<int> b; a.push_back(42); b = a; }bzw.
#include <list> int main() { std::list<int> a; a.push_back(42); std::list<int> b = a; }Und wenn du es unbedingt mit
copymachen willst, dann so:#include <list> #include <algorithm> #include <iterator> int main() { std::list<int> a; std::list<int> b; a.push_back(42); std::copy(a.begin(),a.end(),back_inserter(b)); }wobei
back_inserterDir einen Output-Iterator gibt, der die Elemente bei der Liste hinten anfügt. Dennbist ja leer. Dementsprechend darf der begin-Iterator weder dereferenziert noch inkrementiert werden. Aber genau das passiert instd::copy.Edit: Aber wie ich vorher schon sagte, ist das in deinem Fall mit
copyüberflüssig, weil die vom Compiler generierten Kopieroperationen schon elementweise kopieren und die Kopieroperationen des std::list<>-Elements kopieren auch all die Listenelemente.
-
krümelkacker schrieb:
Und hier ist die Lösung:
Der Punk ist, dass es eine Lösung für ein nicht existentes Problem ist. Hier braucht man nämlich gar keinen selbst definierten Copy Construktor.
-
Ja, das hatte ich ja auch schon erwähnt.
-
krümelkacker schrieb:
Ja, das hatte ich ja auch schon erwähnt.
Hatte ich übersehen sorry.
Prinzipiell ist es ja sehr schön, das ACnut std::Copy() kennt und nicht mit Schleifen oder ähnlichem herumhantiert. Allerdings ist meiner Meinung nach std::Copy() der am meisten überschätzte C++ Algorithmus. Gefühlt 80% aller Verwendungen von std::Copy() lassen sich durch wesentlich bessere Dinge ersetzen z.B. Range-Methoden oder eben gleich Zuweisungoperator oder Copykonstruktor.
-
TNA schrieb:
z.B. Range-Methoden
Stimmt! Das gibt's ja auch noch

Der Vollständigkeit wegen:
#include <list> int main() { std::list<int> a; a.push_back(42); std::list<int> b (a.begin(),a.end()); }(oder auch über list<>::assign)
-
krümelkacker schrieb:
Und hier ist die Lösung:
#include <list> int main() { std::list<int> a; std::list<int> b; a.push_back(42); b = a; }Wenn schon so, wie wäre es mit:
#include <list> int main() { std::list<int> a; a.push_back(42); std::list<int> b(a); }EDIT: Wobei das entspricht praktisch dem
std::list<int> b = a;
-
ja genau das war das problem.
@krümelkacker würde man den nicht die übersichtlichkeit noch mehr verlieren, wenn man alles auf eine klasse "komprimiert"?das problem ist, dass ich nach drei monaten wieder zum ersten mal programmiere und daher vieles aus der erinnerung verloren habe. somit sollte ich eigentlich die back_inserter methode kennen, aber es war leider nicht mehr in erinnerung.
ich persönlich hätte den =, und den copy-ctor auch nicht überladen (es wird ja nicht direkt mit zeigern gearbeitet :)), aber bei einem anderen problem (thema wurde auch hier erstellt), wurde mir gesagt, dass ich das implementieren soll und dann hat es auch funktioniert

das mit den range methoden hatten wir nicht gelernt, aber danke das ich wieder was neues gelernt habe

mfg
ACnut
-
ACnut schrieb:
class Flat // { ... // Size of flat size_t mSize; // Flat owner (if any) TOwner mOwner; };Ein Tip zu deinen Kommentaren (ist zwar off-topic, aber fällt auf): Wenn die Klasse
Flatheißt und die VariablemSize, braucht es nicht noch einen Kommentar "Size of flat". Genau dafür sind präzise Klassen/Funktions/Variablennamen da! Alles andere ist Müll, doppelte Information ist per Definition böse und aus überflüssigen Kommentaren werden in null komma nix falsche, denn du musst nun immer beides pflegen. Also weg damit.
Wenn schon Kommentare, dann sollen sie zusätzliche Informationen liefern, beispielsweise, ob die Flatsize nun Quadratmeter oder Quadratzoll oder Hektar darstellt. Wobei man auch dieses in einem schönen Namen darstellen kann:sizeInSquareMetersoder haltsize_m2.Edit: Bei Größe einer Wohnung mag die Einheit übertrieben erscheinen. Wenn in einem Projekt aber z.B. Minuten, Sekunden und Millisekunden für unterschiedliche Dinge im Spiel sind, sind solche Ergänzungen ein wahrer Segen.
-
ACnut schrieb:
@krümelkacker würde man den nicht die übersichtlichkeit noch mehr verlieren, wenn man alles auf eine klasse "komprimiert"?
Ich weiß jetzt nicht genau, was du damit meinst. 5 Dateien mit 3 Klassen sind höchst unwahrscheinlich ein Minimalbeispiel. Den Fehler so zu isolieren, dass da hinterher nur noch 10 Zeilen stehen, die man sich als Hilfswilliger angucken muss, ist eigentlich Dein Job als Fragesteller. Oft findet man den Fehler so schon von alleine. Ich habe nirgens gesagt, dass das Design in deinem Projekt von 3 Klassen auf eine reduziert werden soll. Minimalbeispiele erhöhen aber Deine Chance, eine hilfreiche Antwort zu bekommen.
ACnut schrieb:
ich persönlich hätte den =, und den copy-ctor auch nicht überladen (es wird ja nicht direkt mit zeigern gearbeitet :)), aber bei einem anderen problem (thema wurde auch hier erstellt), wurde mir gesagt, dass ich das implementieren soll und dann hat es auch funktioniert

Ist Dir denn jetzt klar, wann du diese Operationen selbst definieren musst und wann nicht?
ACnut schrieb:
[...] danke [...]
Gerne.
