Klassendesign: Verbietet ihr alles was ihr nicht braucht?
-
_sone_dreck schrieb:
es werden nur ctor, dtor, copy, assignment von alleine angelegt
In C++11 kommen noch move-Ctor und move-Assignment dazu...
-
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.
-
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.Ich liefer gleich den Standard:
N3337 §12.8 Klausel 9 schrieb:
If the definition of a class X does not explicitly declare a move constructor, one will be implicitly declared
as defaulted if and only if
— X does not have a user-declared copy constructor,
— X does not have a user-declared copy assignment operator,
— X does not have a user-declared move assignment operator,
— X does not have a user-declared destructor, and
— the move constructor would not be implicitly defined as deleted.N3337 §12.8 Klausel 20 schrieb:
If the definition of a class X does not explicitly declare a move assignment operator, one will be implicitly
declared as defaulted if and only if
— X does not have a user-declared copy constructor,
— X does not have a user-declared move constructor,
— X does not have a user-declared copy assignment operator,
— X does not have a user-declared destructor, and
— the move assignment operator would not be implicitly defined as deleted.
-
Genau was ich sagte..
-
N3337 §12.8 Klausel 9 schrieb:
— the move constructor would not be implicitly defined as deleted.
Wann gilt der Punkt denn?
-
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...
-
Nein, implementiert werden sie nicht implizit, allerdings ist es von Vorteil, falls sie vorhanden sind.
Nexus schrieb:
Cyres schrieb:
Die großen 5 (C++11) deklariere ich immer.
Lustig, ich fast nie.
Ich persönlich finde es übersichtlicher, und auf die zwei Zeilen Code kommt es dann echt nicht mehr an. Rein Interesse halber, benutzt (falls du die Wahl hast) du "#pragma once" oder lieber Header-Guards?
-
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?