Klassendesign: Verbietet ihr alles was ihr nicht braucht?
-
Wann immer möglich
#pragma once. In einer plattformunabhängigen Bibliothek allerdings Header-Guards.Hm, fast alle aktuellen Compiler scheinen
#pragma oncezu unterstützen. Kennt ihr Beispiele, wo es nicht funktioniert? Sonst überlege ich mir, das auch in portablem Code zu verwenden.
-
Nexus schrieb:
Wann immer möglich
#pragma once. In einer plattformunabhängigen Bibliothek allerdings Header-Guards.Hm, fast alle aktuellen Compiler scheinen
#pragma oncezu unterstützen. Kennt ihr Beispiele, wo es nicht funktioniert? Sonst überlege ich mir, das auch in portablem Code zu verwenden.Mir sind keine Probleme bekannt, als ich rausgefunden habe, dass auch der GCC (und Clang)
#pragma onceunterstützen, hatte ich auch viel geändert, ich frage deshalb, weil da wieder die beiden Zeilen wären, die man sich bei#pragma oncesparen würde

-
cooky451 schrieb:
Genau was ich sagte..
Nope. Du sagtest "die werden nicht automatisch generiert". Werden sie aber doch, wenn alle anderen auch automatisch generiert werden.
Eisflamme schrieb:
N3337 §12.8 Klausel 9 schrieb:
— the move constructor would not be implicitly defined as deleted.
Wann gilt der Punkt denn?
Ich überlasse das Flöhen des Standards an der Stelle mal anderen, aber da der generierte Move-Ctor einfach alle Member moved, würde ich mal annehmen, dass das dann der Fall ist, wenn einer der Member nicht movable ist.
-
Nexus schrieb:
Kennt ihr Beispiele, wo es nicht funktioniert?
IBM XL C++ for AIX

Meines Wissens erkenne viele Präprozessoren include-Guards aber als das was sie sind und haben eine spezielle Merkvorrichtung dafür, d.h. #pragma once ist dann auch nicht schneller.
-
nahezu alle Borland bzw. CodeGear Compiler erkennen es auch nicht.
-
Nexus schrieb:
Cyres schrieb:
Die großen 5 (C++11) deklariere ich immer.
Lustig, ich fast nie.
Zumindest was die Grossen Drei angeht, sehe ich es von Vorteil, wenn die Member bereits Wertsemantik besitzen und automatisch kopiert werden. Das spart viel Boilerplatecode und auch mögliche Fehler, weil die Kopie eines Members vergessen wird. Bei Klassen, die Exceptions werfen, muss man allerdings etwas aufpassen...
Kannst du bitte das etwas genauer erklären, warum es bei Klassen die Execptions werfen schwieriger ist die rulez-of-three zu implementieren?
-
_sone_dreck schrieb:
Kannst du bitte das etwas genauer erklären, warum es bei Klassen die Execptions werfen schwieriger ist die rulez-of-three zu implementieren?
Es geht vor allem darum, was passiert wenn die entsprechenden Operationen der Member Exceptions werfen. Beispiel:
class AssignmentThrows; //Name sagt alles... class Problematic { int* p1; AssignmentThrows at; int* p2; //INVARIANTE: p2 > p1 };So, was passiert, wenn ich ein "Problematic" einem anderen zuweise?
p1 wird kopiert. OK. at wird kop...BUMM
Übrig bleibt ein "Problematic", bei dem p1 geändert wurde, p2 aber nicht. Die Invariante wird vermutlich nicht mehr gelten, und alles was sich darauf verlässt (z.B. der Destruktor) spielt Russisch Roulette. Kurz: der default-generierte op= ist nicht exceptoinsicher.
Das ist jetzt ein sehr merkwürdig konstruiertes Beispiel, aber es zeigt die Problematik, und die gibts in allen Formen, Farben und Geschmacksrichtungen.
-
Da nimmt man ja auch std::unique_ptr wenn p1 ein Objekt hält, ansonsten eben gleich ein Int anstelle eines Pointers auf int nutzen

Oder liege ich da so falsch?
Die Bombe explodiert doch hier schon beim Anlegen des Objekte und nicht erst beim kopieren???
Ich bin verwirrt...
-
pumuckl schrieb:
cooky451 schrieb:
Genau was ich sagte..
Nope. Du sagtest "die werden nicht automatisch generiert". Werden sie aber doch, wenn alle anderen auch automatisch generiert werden.
Ich tu jetzt einfach mal so, als ob cooky das richtige meinte.
cooky451 schrieb:
pumuckl schrieb:
_sone_dreck schrieb:
es werden nur ctor, dtor, copy, assignment von alleine angelegt
In C++11 kommen noch move-Ctor und move-Assignment dazu...
Noch nicht ganz wach?
Die werden so nicht automatisch generiert.
-
Butterbrot schrieb:
Da nimmt man ja auch std::unique_ptr wenn p1 ein Objekt hält, ansonsten eben gleich ein Int anstelle eines Pointers auf int nutzen

Oder liege ich da so falsch?
Ich habe die int* jetzt als Beispiel genommen, einfach um aufzuzeigen, dass es darum geht, dass evtl voneinander abhängige Objekte nur zum Teil kopiert werden, bevor die Exception zuschlägt. Meinetwegen nimm zwei ints a und b, die als Invariante haben, dass a+b=100 oder etwas in der Art (ja ich weiß, da gibts auch wieder ein "aber"...)
Butterbrot schrieb:
Die Bombe explodiert doch hier schon beim Anlegen des Objekte und nicht erst beim kopieren???
Assignment ist der Zuweisungsoperator. Es ist nicht der Copy-Ctor gemeint. Gehe davon aus, dass beide Objekte voneinander unabhängig erstellt wurden (Ctor wirft keine Exception) und irgendwann danach das eine dem anderen zugewiesen wird.
-
Was passiert eigentlich wenn a und b ein Objekt mit Resourcen ist und ich die Zuweisung a = b mache? Dann habe ich zwei mal die gleiche Resource in zwei verschiedenen Objekten?
-
Butterbrot schrieb:
Was passiert eigentlich wenn a und b ein Objekt mit Resourcen ist und ich die Zuweisung a = b mache? Dann habe ich zwei mal die gleiche Resource in zwei verschiedenen Objekten?
Wenn du die Big5, besonders den op= nicht ordentlich implementierst, ja. Und im Normalfall kommst du in Teufels Küche, wenn das erste Objekt zerstört wurde und das zweite Objekt sie versucht weiter zu nutzen. Spätestens aber wenn das zweite Objekt zerstört wird und der Dtor die gleiche Ressource das zweite mal freigeben will...
-
Zu den beiden:
A(const A& rhs) A& operator=(const A& rhs)kommen dann noch jetzt die beiden dazu:
A(A&& rhs) A& operator=(A&& rhs)Dann sind wir mit den Destruktor bei den neuen Big5, richtig?
-
Butterbrot schrieb:
Zu den beiden:
A(const A& rhs) A& operator=(const A& rhs)kommen dann noch jetzt die beiden dazu:
A(A&& rhs) A& operator=(A&& rhs)Dann sind wir mit den Destruktor bei den neuen Big5, richtig?
Jau.
-
Und wenn ein Objekt z.B. mit Resourcen nur weitergegeben und nicht kopiert werden soll, dann nimmt man nur die Move-Semantik und setzt die Zuweisung auf private, oder?
-
Butterbrot schrieb:
Und wenn ein Objekt z.B. mit Resourcen nur weitergegeben und nicht kopiert werden soll, dann nimmt man nur die Move-Semantik und setzt die Zuweisung auf private, oder?

Ich glaube, du hast es kapiert.
Beispiel:std::vector<std::string> benutzernamen; //... { std::string str = "pumuckl und Meister Eder";//Irgendein zu bearbeitender string str.erase(7);//Bearbeiten benutzernamen.push_back( std::move(str) );//Du willst str nicht weiter benutzen, also moven }
-
Sone schrieb:
Ich tu jetzt einfach mal so, als ob cooky das richtige meinte.
Hey, klau nicht meine Beiträge.
