Komisches Verhalten von std::reverse bei Vectoren aus Objekten eigener Klasse
-
Hallo zusammen,
mal wieder ein Problem mit meiner Klasse TSongs:
Ich hab mal ein kleines Testprogramm geschrieben:
int main(int argc, char* argv[]) { TStrings *text = new TStringList; text->Text = "abc\r\ndefg\r\n\0"; vector<TSong> vec; /*vec.push_back("48"); vec.push_back("56"); vec.push_back("24"); vec.push_back("89");*/ vec.push_back(TSong("RW", "feel", "esc", 78, text)); vec.push_back(TSong("RaW", "feel", "esc", 78, text)); vec.push_back(TSong("RoW", "feel", "esc", 78, text)); vec.push_back(TSong("fcb", "feel", "esc", 78, text)); delete text; text = NULL; cout << "Vector:" << endl; for(int i = 0; i < vec.size(); i++) cout << static_cast<string>(vec[i]) << endl; cout << endl; reverse(vec.begin(), vec.end()); cout << "Vector reversed:" << endl; for(int i = 0; i < vec.size(); i++) cout << static_cast<string>(vec[i]) << endl; cout << endl; getch(); return 0; }
Der Umwandlungs-Operator von TSong für std::string ist so definiert, dass er den ersten Parameter des Konstruktors zurückgibt. Die erste ausgabe sollte also lauten:
RW
RaW
RoW
fcbDie zweite eben umgekehrt.
Seltsamerweise ist die zweite Ausgabe genau so wie die erste.
Bei einem vector<int> oder einem vector<string> gibts keine Probleme.
-
Falls es euch helfen sollte, hier die deklaration von TSong:
#include <vcl.h> #include <string> #ifndef SongH #define SongH class TSong { private: String FArtist; TStrings * FText; String FTitle; String FAlbum; short FTrackNo; protected: public: TSong() { FArtist = ""; FText = new TStringList; FTitle = ""; FAlbum = ""; FTrackNo = -1; } TSong(const TSong &source) { Text = new TStringList; FArtist = source.FArtist; FText->Assign(source.FText); FTitle = source.FTitle; FAlbum = source.FAlbum; FTrackNo = source.FTrackNo; } TSong(String AArtist, String ATitle, String AAlbum, short ATrackNo, TStrings * AText); virtual ~TSong() { delete FText; } const TSong &operator=(const TSong &source) { if(this == &source) return *this; TSong temp(source); TStrings *pText = FText; FText = temp.FText; temp.FText = pText; return *this; } friend const bool operator <(const TSong &left, const TSong &right); friend const bool operator <=(const TSong &left, const TSong &right); friend const bool operator >(const TSong &left, const TSong &right); friend const bool operator >=(const TSong &left, const TSong &right); friend const bool operator ==(const TSong &left, const TSong &right); __property String Artist = { read = FArtist, write = FArtist }; __property TStrings * Text = { read = FText, write = FText }; __property String Title = { read = FTitle, write = FTitle }; __property String Album = { read = FAlbum, write = FAlbum }; __property short TrackNo = { read = FTrackNo, write = FTrackNo }; operator std::string() { return Artist.c_str(); } }; //--------------------------------------------------------------------------- const bool operator ==(const TSong &left, const TSong &right) { return (left.FArtist == right.FArtist && left.FTitle == right.FTitle); } //--------------------------------------------------------------------------- const bool operator <(const TSong &left, const TSong &right) { return ((left.FArtist < right.FArtist) || (left.FArtist == right.FArtist && left.FTitle < right.FTitle)); } //--------------------------------------------------------------------------- const bool operator <=(const TSong &left, const TSong &right) { return left < right || left == right; } //--------------------------------------------------------------------------- const bool operator >(const TSong &left, const TSong &right) { return right < left; } //--------------------------------------------------------------------------- const bool operator >=(const TSong &left, const TSong &right) { return right <= left; } //--------------------------------------------------------------------------- #endif
-
sieh dir einmal den operator = an.
du änderst eigentlich nur FText die anderen membervariablen werden nicht geändert.
er sollte wahrscheinlic so aussehen( ohne zu wissen wie TStringList funktioniert)const TSong &operator=(const TSong &source) { if(this == &source) return *this; delete FText; FArtist = source.FArtist; FText = new TStringList; FText->Assign(source.FText); FTitle = source.FTitle; FAlbum = source.FAlbum; FTrackNo = source.FTrackNo; return *this; }
ausserddem sollte es wahrscheinlich heissen:
TSong(const TSong &source) { FText = new TStringList; // nicht Text=new TStringList; FArtist = source.FArtist; FText->Assign(source.FText); FTitle = source.FTitle; FAlbum = source.FAlbum; FTrackNo = source.FTrackNo; }
Kurt
-
1.: Danke, das wars!
Das passiert wenn man mal bei der Implementierung eines Operators nicht aufpasst...Zum Zweiten: Geht beides (wegen der Borland-properties), aber FText ist natürlich konsequenter.
Edit: Nochmal zum operator=:
Das new TStringList ist überflüssig, weil das schon im Ctor aufgerufen wird.
-
Eßer schrieb:
Das new TStringList ist überflüssig, weil das schon im Ctor aufgerufen wird.
Da ich nicht weiss wie diese TStringList arbeitet habe ich
delete FText; // alte liste löschen da sonst memleak FArtist = source.FArtist; FText = new TStringList;// neue liste anlegen
geschrieben da ich annehme dass ohne delete dadurch die alten daten nicht freigegeben werden. Wann aber TStringList::Assign() die alten daten löchscht dann kannst du dir delete FText; und FText=new TStringList; natürlich sparen.
Kurt.