Klasse X sortieren?
-
Erhard Henkes schrieb:
if(&x == this) { std::cout << "Selbstzuweisung mit op= verhindert!" << endl; return *this; }
Das würde ich nicht machen, da Selbstzuweisung ein "natürliches Phänomen" ist. Wenn die Klasse als "Sonde" dienen soll, würde ich die built-in Funktionalität von int nicht brechen. Also ein einfaches
if (&x == this) { std::cout << "Selbstzuweisung mit op=" << std::endl; }
reicht imo.
btw:
Beim Editieren deines Codes ist mir aufgefallen, dass std:: mal benutzt wird und mal nicht.
-
Ja, das ist richtig, hier muss man nicht unbedingt abfangen.
Beim Editieren deines Codes ist mir aufgefallen, dass std:: mal benutzt wird und mal nicht.
Klasse als Header sollte kein namespace std freigeben (ist oben nur aus header und cpp kombiniert).
-
z.B. Vergleich list und vector:
int main () { const int N = 3; Xint x; list<Xint> l; list<Xint>::iterator it; for(int i=0; i<N; ++i) { x.setNum(i); l.push_back(x); } cout << endl; x.setNum(42); it = l.begin(); l.insert(++it,x); cout << endl; for(it=l.begin();it!=l.end();++it) { cout << *it << endl; } getch(); }
0x22ff58: ctor 0x3f2540: copycon von 0x22ff58 0x3f2550: copycon von 0x22ff58 0x3f2560: copycon von 0x22ff58 0x3f2570: copycon von 0x22ff58 0 42 1 2
//... vector<Xint> l; vector<Xint>::iterator it; //...
0x22ff58: ctor 0x3f2528: copycon von 0x22ff58 0x3f2530: copycon von 0x3f2528 0x3f2534: copycon von 0x22ff58 0x3f2528: dtor 0x3f25c8: copycon von 0x3f2530 0x3f25cc: copycon von 0x3f2534 0x3f25d0: copycon von 0x22ff58 0x3f2530: dtor 0x3f2534: dtor 0x3f25d4: copycon von 0x3f25d0 0x22fe40: copycon von 0x22ff58 0x3f25d0: op= von 0x3f25cc 0x3f25cc: op= von 0x22fe40 0x22fe40: dtor 0 42 1 2
Da ich eine solche Visualisierung nirgends gefunden habe, bastele ich mir diese "Sonde". Gibt es irgendwo etwas Ähnliches/Besseres?
-
Was praktisch wäre: bau noch static Zähler ein, die direkt die Anzahl der CopyCtor, Ctor, Dtor, op=, etc. aufrufe mitzählen.
So dass du dann nur noch
Xint::statistik(cout);
machen musst, um eine schöne statistik zu erhalten - und dafür die internen ausgaben per #define an und abschaltbar machen.Der Vorteil: du kannst die Klasse dann auch in ein richtiges Programm einbauen und müllst dir die Ausgabe nicht zu. Und die Statistik kann man dann schön zB in Dateien schreiben um sie zu speichern...
PS:
im op<< kann Xint const sein
-
Danke! Gute Idee, schon realisiert:
[EDIT] Funktion reset (s.u.) ebenfalls bereits eingebaut [\EDIT]#include <deque> #include <vector> #include <list> #include <algorithm> #include <iostream> #include <conio.h> using namespace std; //#define _TEST_ class Xint { private: int num; static int countCtor; static int countDtor; static int countCopycon; static int countOpAssign; public: Xint() { #ifdef _TEST_ std::cout<<this<<": "<<"ctor"<<std::endl; #endif ++countCtor; } ~Xint() { #ifdef _TEST_ std::cout<<this<<": "<<"dtor"<<std::endl; #endif ++countDtor; } Xint(const Xint& x) { #ifdef _TEST_ std::cout << this << ": " << "copycon von " << &x << std::endl; #endif num = x.getNum(); ++countCopycon; } Xint& operator=(const Xint& x) { if (&x == this) { #ifdef _TEST_ std::cout << "Selbstzuweisung mit op=" << std::endl; #endif } #ifdef _TEST_ std::cout << this << ": " << "op= von " << &x << std::endl; #endif num = x.getNum(); ++countOpAssign; return *this; } int getNum() const {return num;} void setNum(int val) {num = val;} static void statistik(ostream&); static void reset(); }; int Xint::countCtor = 0; int Xint::countDtor = 0; int Xint::countCopycon = 0; int Xint::countOpAssign = 0; void Xint::statistik(ostream& os) { os << "Ctor: " << countCtor << endl << "Dtor: " << countDtor << endl << "Copycon: " << countCopycon << endl << "op=: " << countOpAssign; } void Xint::reset() { countCtor = 0; countDtor = 0; countCopycon = 0; countOpAssign = 0; } ostream& operator<< (ostream& os, const Xint& x) { os << x.getNum(); return os; } bool operator< (const Xint& a, const Xint& b) { return a.getNum() < b.getNum(); } bool operator> (const Xint& a, const Xint& b) { return a.getNum() > b.getNum(); } bool operator== (const Xint& a, const Xint& b) { return a.getNum() == b.getNum(); } int main () { const int N = 3; Xint x; list<Xint> l; list<Xint>::iterator it; for(int i=0; i<N; ++i) { x.setNum(i); l.push_back(x); } cout << endl; x.setNum(42); it = l.begin(); l.insert(++it,x); cout << endl; for(it=l.begin();it!=l.end();++it) { cout << *it << endl; } cout << endl; Xint::statistik(cout); getch(); }
0 42 1 2 Ctor: 1 Dtor: 0 Copycon: 4 op=: 0
-
ein reset() (setzt alle statistik vars auf 0) wäre dann auch noch praktisch - wenn man nur einen kleinen teil des codes testen will, oder zB list und deque im selben programm
-
Hübsche Idee, bereits implementiert (s.o.).
Beispiel: list vs. deque
int main () { const int N = 10; Xint x; list<Xint> l; list<Xint>::iterator it; for(int i=0; i<N; ++i) { x.setNum(i); l.push_back(x); } cout << endl; x.setNum(42); it = l.begin(); l.insert(++it,x); cout << endl; l.erase(--it); cout << endl; for(it=l.begin();it!=l.end();++it) { cout << *it << endl; } cout << endl; Xint::statistik(cout); Xint::reset(); cout << endl << endl; deque<Xint> d; deque<Xint>::iterator iter; for(int i=0; i<N; ++i) { x.setNum(i); d.push_back(x); } cout << endl; x.setNum(42); iter = d.begin(); d.insert(++iter,x); cout << endl; d.erase(--iter); cout << endl; for(iter=d.begin();iter!=d.end();++iter) { cout << *iter << endl; } cout << endl; Xint::statistik(cout); getch(); }
Kurzform:
0 1 2 3 4 5 6 7 8 9 Ctor: 1 Dtor: 1 Copycon: 11 op=: 0 0 1 2 3 4 5 6 7 8 9 Ctor: 0 Dtor: 3 Copycon: 13 op=: 2
Vorteil für list!
Langform:
0x22ff58: ctor 0x3f2540: copycon von 0x22ff58 0x3f2550: copycon von 0x22ff58 0x3f2560: copycon von 0x22ff58 0x3f2570: copycon von 0x22ff58 0x3f2580: copycon von 0x22ff58 0x3f2590: copycon von 0x22ff58 0x3f25a0: copycon von 0x22ff58 0x3f25b0: copycon von 0x22ff58 0x3f25c0: copycon von 0x22ff58 0x3f25d0: copycon von 0x22ff58 0x3f25e0: copycon von 0x22ff58 0x3f25e0: dtor 0 1 2 3 4 5 6 7 8 9 Ctor: 1 Dtor: 1 Copycon: 11 op=: 0 0x3f3968: copycon von 0x22ff58 0x3f396c: copycon von 0x22ff58 0x3f3970: copycon von 0x22ff58 0x3f3974: copycon von 0x22ff58 0x3f3978: copycon von 0x22ff58 0x3f397c: copycon von 0x22ff58 0x3f3980: copycon von 0x22ff58 0x3f3984: copycon von 0x22ff58 0x3f3988: copycon von 0x22ff58 0x3f398c: copycon von 0x22ff58 0x22fd80: copycon von 0x22ff58 0x22fb60: copycon von 0x3f3968 0x3f3d6c: copycon von 0x22fb60 0x22fb60: dtor 0x3f3968: op= von 0x22fd80 0x22fd80: dtor 0x3f3968: op= von 0x3f3d6c 0x3f3d6c: dtor 0 1 2 3 4 5 6 7 8 9 Ctor: 0 Dtor: 3 Copycon: 13 op=: 2
Hat noch jemand interessante Ideen für diese Klasse, die in STL-Containern z.B. als Ersatz dienen soll für ein einfaches int.
-
Habe nun auch noch Farbe bei der Ausgabe auf Konsole implementiert:
#define _TEST_ #include <windows.h> #include <conio.h> #include <iostream> /* 0 BLACK, 1 BLUE, 2 GREEN, 3 CYAN, 4 RED, 5 MAGENTA, 6 BROWN, 7 LIGHTGRAY, 8 DARKGRAY, 9 LIGHTBLUE, 10 LIGHTGREEN, 11 LIGHTCYAN, 12 LIGHTRED, 13 LIGHTMAGENTA, 14 YELLOW, 15 WHITE */ void textcolor(WORD color) { SetConsoleTextAttribute(::GetStdHandle(STD_OUTPUT_HANDLE), color); } const int farbe1 = 3; const int farbe2 = 15; class Xint { private: int num; static int countCtor; static int countDtor; static int countCopycon; static int countOpAssign; public: Xint() { #ifdef _TEST_ textcolor(farbe1); std::cout << this << ": " << "ctor" << std::endl; textcolor(farbe2); #endif ++countCtor; } ~Xint() { #ifdef _TEST_ textcolor(farbe1); std::cout << this << ": " << "dtor" << std::endl; textcolor(farbe2); #endif ++countDtor; } Xint(const Xint& x) { #ifdef _TEST_ textcolor(farbe1); std::cout << this << ": " << "copycon von " << std::dec << &x << std::endl; textcolor(farbe2); #endif num = x.getNum(); ++countCopycon; } Xint& operator=(const Xint& x) { if (&x == this) { #ifdef _TEST_ textcolor(farbe1); std::cout << "Selbstzuweisung mit op=" << std::endl; textcolor(farbe2); #endif } #ifdef _TEST_ textcolor(farbe1); std::cout << this << ": " << "op= von " << std::dec << &x << std::endl; textcolor(farbe2); #endif num = x.getNum(); ++countOpAssign; return *this; } int getNum() const {return num;} void setNum(int val) {num = val;} static void statistik(std::ostream&); static void reset(); }; int Xint::countCtor = 0; int Xint::countDtor = 0; int Xint::countCopycon = 0; int Xint::countOpAssign = 0; void Xint::statistik(std::ostream& os) { textcolor(farbe1); os << "Ctor: " << countCtor << std::endl << "Dtor: " << countDtor << std::endl << "Copycon: " << countCopycon << std::endl << "op=: " << countOpAssign; textcolor(farbe2); } void Xint::reset() { countCtor = 0; countDtor = 0; countCopycon = 0; countOpAssign = 0; } std::ostream& operator<< (std::ostream& os, const Xint& x) { os << x.getNum(); return os; } bool operator< (const Xint& a, const Xint& b) { return a.getNum() < b.getNum(); } bool operator> (const Xint& a, const Xint& b) { return a.getNum() > b.getNum(); } bool operator== (const Xint& a, const Xint& b) { return a.getNum() == b.getNum(); } bool operator!= (const Xint& a, const Xint& b) { return a.getNum() != b.getNum(); }
-
Erhard Henkes schrieb:
Habe nun auch noch Farbe bei der Ausgabe auf Konsole implementiert:
Hm, und damit ist es jetzt nicht mehr portabel, nimm doch die Improved Console wenn Du unbedingt bunte Ausgabe willst!
btw: Was hältst Du davon Deine #ifdefs nicht auf TEST testen zu lassen sondern auf NDEBUG oä?
-
Erhard Henkes schrieb:
Habe nun auch noch Farbe bei der Ausgabe auf Konsole implementiert
Na wenn das mal nix is.
-
Hm, und damit ist es jetzt nicht mehr portabel, nimm doch die Improved Console wenn Du unbedingt bunte Ausgabe willst!
Uups, stimmt. Die Linuxer sind draußen. Improved Konsole, gute Idee, habe ich mir noch nie angeschaut. Geht das auf allen Plattformen? Thx.