Die Präsentation wird geladen. Bitte warten

Die Präsentation wird geladen. Bitte warten

C++11 Defaulted & Deleted Functions / 48 C++11 Defaulted & Deleted Functions Detlef Wilkening

Ähnliche Präsentationen


Präsentation zum Thema: "C++11 Defaulted & Deleted Functions / 48 C++11 Defaulted & Deleted Functions Detlef Wilkening"—  Präsentation transkript:

1 C++11 Defaulted & Deleted Functions / 48 C++11 Defaulted & Deleted Functions Detlef Wilkening &

2 C++11 Defaulted & Deleted Functions / 48 Themen:  6 spezielle Funktionen in Klassen und ihre Erzeugungs-Regeln  Explicitly Defaulted Functions  Deleted Functions  ISO & Links

3 C++11 Defaulted & Deleted Functions / 48 6 spezielle Member- Funktionen in Klassen und ihre Erzeugungs-Regeln

4 C++11 Defaulted & Deleted Functions / 48  Spezielle Member-Funktionen einer Klasse "A" Standard-KonstruktorA() Destruktor~A() Kopier-KonstruktorA(const A&) Kopier-Zuweisungs-OperatorA& operator=(const A&) Move-KonstruktorA(A&&) Move-Zuweisungs-OperatorA& operator=(A&&)

5 C++11 Defaulted & Deleted Functions / 48  Standard-Konstruktor: A() Der implizite Standard-Konstruktor wird nur dann erzeugt, wenn kein anderer Konstruktor explizit deklariert wurde, und wenn er erzeugbar ist

6 C++11 Defaulted & Deleted Functions / 48  Destruktor: ~A() Der implizite Destruktor wird immer erzeugt, außer es gibt einen user-deklarierten Destruktor, oder er ist nicht erzeugbar.

7 C++11 Defaulted & Deleted Functions / 48  Kopier-Konstruktor: A(const A&) Der implizite Kopier-Konstruktor wird erzeugt, wenn: er nicht explizit deklariert wurde, er generierbar ist, d.h. alle Elemente der Klasse kopierbar sind, es keinen expliziten Move-Konstruktor gibt (C++11), und es keinen expliziten Move-Zuweisungs-Operator gibt (C++11) Zusätzlich in C++11: Wenn der Destruktor oder der Kopier-Zuweisungs-Operator explizit deklariert wurde, dann ist die Erzeugung des Kopier-Konstruktors deprecated.  Kopier-Zuweisungs-Operator: A& operator=(const A&) Der implizite Kopier-Zuweisungs-Operator wird erzeugt, wenn: er nicht explizit deklariert wurde, er generierbar ist, d.h. alle Elemente der Klasse kopier-zuweisbar sind, es keinen expliziten Move-Konstruktor gibt (C++11), und es keinen expliziten Move-Zuweisungs-Operator gibt (C++11) Zusätzlich in C++11: Wenn der Destruktor oder der Kopier-Konstruktor explizit deklariert wurde, dann ist die Erzeugung des Kopier-Zuweisungs-Operators deprecated.

8 C++11 Defaulted & Deleted Functions / 48  Move-Konstruktor: A(A&&) Der implizite Move-Konstruktor wird erzeugt, wenn: er nicht explizit deklariert wurde, kein expliziter Kopier-Konstruktor deklariert wurde, kein expliziter Kopier-Zuweisungs-Operator deklariert wurde, kein expliziter Move-Zuweisungs-Operator deklariert wurde, kein expliziter Destruktor deklariert wurde, und er generierbar ist  D.h. wenn alle Elemente der Klasse "movebar" sind  Move-Zuweisungs-Operator: A& operator=(A&&) Der implizite Move-Zuweisungs-Operator wird erzeugt, wenn: er nicht explizit deklariert wurde, kein expliziter Kopier-Konstruktor deklariert wurde, kein expliziter Kopier-Zuweisungs-Operator deklariert wurde, kein expliziter Move-Konstruktor deklariert wurde, kein expliziter Destruktor deklariert wurde, und er generierbar ist  D.h. wenn alle Elemente der Klasse "move-zuweisbar" sind

9 C++11 Defaulted & Deleted Functions / 48  C++ 11 erlaubt eine exakte Steuerung der Generierung dieser 6 speziellen Member-Funktionen Dafür gibt es in C++11 nun die Möglichkeit mit "=default" oder "=delete" die Generierung zu aktivieren oder zu verbieten Siehe ISO/IEC 14882, Kapitel 12.1, 12.4, 12.7, 12.8 und

10 C++11 Defaulted & Deleted Functions / 48 Explicitly Defaulted Functions

11 C++11 Defaulted & Deleted Functions / 48  Explicitly-defaulted Functions So nennt der Standard sie: ISO/IEC 14882:2011(E) § Bezieht sich nur auf die speziellen Member-Funktionen Nur:  Standard-KonstruktorA()  Destruktor~A()  Kopier-KonstruktorA(const A&)  Kopier-Zuweisungs-OperatorA& operator=(const A&)  Move-KonstruktorA(A&&)  Move-Zuweisungs-OperatorA& operator=(A&&) Denn diese könnten nicht erzeugt werden Bzw. werden speziell benötigt (z.B. virtueller Destruktor)

12 C++11 Defaulted & Deleted Functions / 48  Wird eine der speziellen Member-Funktionen nicht erzeugt, so kann man die Erzeugung erzwingen = default hinter die Funktions-Deklaration class A { public: A() = default; ~A() = default; A(const A&) = default; A& operator=(const A&) = default; A(A&&) = default; A& operator=(A&&) = default; };

13 C++11 Defaulted & Deleted Functions / 48  Haupt-Anwendung: Erzeugungs-Regeln verhindern die automatische Erzeugung Funktion soll trotzdem vorhanden sein Achtung Auch "explizit defaulted Funktionen" sind user-deklarierte Funktionen und greifen daher in die Erzeugungs-Regeln ein class A { public: A() = default; // Soll normal da sein A(int); // Verhindert Erzeugung vom Standard-Konstruktor private: std::string s; };

14 C++11 Defaulted & Deleted Functions / 48  Weitere Anwendungen Veränderung des Zugriffs-Bereichs Virtueller Destruktor Trivialer Typ

15 C++11 Defaulted & Deleted Functions / 48  Veränderung des Zugriffs-Bereichs Beispiel Standard-Konstruktor wäre vorhanden Aber public – soll protected sein Möglich mit = default class A { public: virtual ~A(); protected: A() = default; // Soll normal da sein, aber protected private: std::string s; };

16 C++11 Defaulted & Deleted Functions / 48  Virtueller Destruktor Basis-Klassen sollten einen virtuellen Destruktor haben Mußte früher häufig explizit leer implementiert werden Heute einfach mit = default class A { public: virtual ~A() = default; // Normal vorhanden, aber virtual };

17 C++11 Defaulted & Deleted Functions / 48  Trivialer Typ Eine Klasse mit z.B. einem expliziten Standard-Konstruktor ist nicht trivial Kein POD – „Plain Old Data“ => Compiler kann nicht beliebig optimieren Funktionen dürfen nicht übersprungen werden Storage darf nicht wiederverwendet werden memcpy kann nicht verwendet werden Type-Trait Optimierungen für PODs greifen nicht => Trivialer Typ ist häufig erstrebenswert  Wichtig Alle Funktionen werden mit „= default“ so erzeugt, wie die automatisch generierten Funktionen erzeugt worden wären.

18 C++11 Defaulted & Deleted Functions / 48  Typ ist trotz lauter expliziter spezieller Funktionen ein POD struct Trivial { Trivial() = default; Trivial(const Trivial&) = default; Trivial(Trivial&&) = default; Trivial& operator=(const Trivial&) = default; Trivial& operator=(Trivial&&) = default; ~Trivial() = default; };

19 C++11 Defaulted & Deleted Functions / 48  Besonderheiten bei „explicitly defaulted functions“: Variationen der speziellen Funktionen constexpr Default ausserhalb der Klassen-Definition

20 C++11 Defaulted & Deleted Functions / 48  Variationen der speziellen Funktionen Bei der Deklaration der speziellen Funktionen mit „= default“ sind nur minimale Variationen erlaubt Kopier-Konstruktor, Kopier-Zuweisungs-Operator, Move-Konstruktor und Move- Zuweisungs-Operator dürfen auch non-const und/oder volatile Referenzen haben Der Rückgabe-Typ der Zuweisungs-Operatoren ist nicht frei Exception-Spezifikation muß matchen Parameter mit Default-Argumenten sind weder beim Standard-Konstruktor, Kopier-Konstruktor noch Move-Konstruktor mit „= default“ erlaubt class A { public: A(int=0) = default; // Fehler – Default-Argument ~A() throw(int) = default; // Fehler – Exceptions-Sp. void operator=(A&&) = default; // Fehler - Rückgabe-Typ A(A&) = default; // Okay, auch non-const Referenz };

21 C++11 Defaulted & Deleted Functions / 48  constexpr Eine explizit defaulted Funktion kann nur „constexpr“ sein, wenn es auch die normale automatische Funktion wäre struct A { constexpr A() = default; // Fehler - constexpr private: int i; };

22 C++11 Defaulted & Deleted Functions / 48  Default ausserhalb der Klassen-Definition Spezielle Funktionen können auch ausserhalb der Klassen-Definition explizit defaulted werden Achtung – solche Klassen sind dann niemals triviale Typen Denn unterschiedliche Nutzungs-Stellen könnten unterschiedliche Definitionen sehen struct NonTrivial { NonTrivial(); }; NonTrivial:: NonTrivial() = default; // Okay // Aber nicht trivial

23 C++11 Defaulted & Deleted Functions / 48  Fazit Sie können alle automatisch generierbaren speziellen Member-Funktionen (ohne new & delete) in C++11 explizit default machen Sie werden dann „normal“ generiert Daher triviale Typen bleiben triviale Typen Damit können Unterdrückte automatische Generierungen wieder aktiviert werden Zugriffsbereiche verändert werden Virtuelle Destruktoren vereinfacht werden Typen trivial gehalten werden

24 C++11 Defaulted & Deleted Functions / 48 Deleted Functions

25 C++11 Defaulted & Deleted Functions / 48  "= delete" hinter einer Funktion löscht diese Funktion Damit kann man die Generierung von speziellen Funktionen unterdrücken  Haupt-Anwendung Verbieten, dass ein Typ kopierbar und/oder movebar ist

26 C++11 Defaulted & Deleted Functions / 48  Klassen sollten die Regel der 3, 4, 5, 6 oder 0 erfüllen  Regel-der-3 - C++03 Wenn eine Klasse einen expliziten Destruktor, Kopier-Konstruktor oder Kopier-Zuweisungs-Operator hat, dann ist es extrem wahrscheinlich das auch die anderen beiden speziellen Funktionen explizit definiert werden müssen.  Regel-der-4 - besseres C++03 Ohne eine typ-spezifische Swap-Funktion kann man den Kopier-Konstruktor nur schwer sinnvoll und exception-sicher implementieren Copy&Swap Idiom  Regel-der-5 - C++11 Regel-der-3 zusätzlich mit Move-Konstruktor und Move-Zuweisungs-Operator  Regel-der-6 - besseres C++11 Typ-spezifische Swap-Funktion ist ein Stück performanter als Swap mit Move  Regel-der-0 - C++11 Man nutzt RAII Klassen und benötigt keine spezielle Member-Funktion

27 C++11 Defaulted & Deleted Functions / 48  Problem Typ hat expliziten Destruktor, und die implizite Funktionen wie z.B. Kopier- Konstruktor funktionieren nicht korrekt  Lösungen in C++03 Kopier-Konstruktor und -Zuweisungs-Operator privat deklarieren, aber nicht implementieren Beispiel siehe nächste Folie Klasse privat ableiten von boost::noncopyable Beispiel siehe nächste Folie

28 C++11 Defaulted & Deleted Functions / 48 class NonCopyable : boost::noncopyable // Achtung - kein POD { public: // Impliziter Standard-Konstruktor ist auch nicht trivial }; class NonCopyable // Achtung - kein POD { public: NonCopyable() {} // Achtung - nicht trivial private: NonCopyable(const NonCopyable&); // ohne Impl. NonCopyable& operator=(const NonCopyable&); // ohne Impl. };

29 C++11 Defaulted & Deleted Functions / 48  Nachteile Standard-Konstruktor muß möglicherweise explizit gemacht werden => Standard-Konstruktor ist nicht trivial => kein POD Friends und Member-Funktionen haben immer noch Zugriff => erst Linker-Fehler schlägt zu Die Intention ist schwer zu verstehen Obwohl es ein akzeptiertes und verbreitetes Idiom ist

30 C++11 Defaulted & Deleted Functions / 48  Lösung in C++11 Funktion mit "= delete" entfernen class NonCopyable // Ist POD { public: NonCopyable() = default; // Ist trivial NonCopyable(const NonCopyable&) = delete; NonCopyable& operator=(const NonCopyable&) = delete; };

31 C++11 Defaulted & Deleted Functions / 48  Vorteile Standard-Konstruktor ist durch "= default" weiterhin trivial => Klasse kann also ein POD sein Trotz Public-Funktionen gibt es beim Kopieren und Kopier-Zuweisen immer einen Compiler-Fehler Denn die Funktionen sind "deleted" Die Intention ist sofort klar  Hinweis Der Typ "NonCopyable" ist auch nicht movebar Denn die explizite Deklaration von z.B. dem Kopier-Konstruktor reicht Move-Konstruktor und -Zuweisungs-Operator werden nicht implizit erzeugt

32 C++11 Defaulted & Deleted Functions / 48  Will man Typ haben, der movebar aber nicht kopierbar ist Wie z.B. beim C++11 "std::unique_ptr" Kopier-Operationen "deleten" Move-Operationen "defaulten" class OnlyMoveable { public: OnlyMoveable() = default; OnlyMoveable(const OnlyMoveable&) = delete; OnlyMoveable& operator=(const OnlyMoveable&) = delete; OnlyMoveable(OnlyMoveable&&) = default; OnlyMoveable& operator=(OnlyMoveable&&) = default; };

33 C++11 Defaulted & Deleted Functions / 48  Aber es gibt auch noch andere Anwendungsfälle für = delete  Z.B. eine Klasse, die nicht erzeugbar und zerstörbar ist Vielleicht als Sammlung von statischen Funktionen Oder warum auch immer  => Standard-Konstruktor deleten Optional auch noch deleten des Destruktors Aber eigentlich nicht notwändig class A { public: A() = delete; ~A() = delete; };

34 C++11 Defaulted & Deleted Functions / 48  Man kann nicht nur die speziellen Member-Funktionen deleten Das geht auch für andere generierte Funktionen New & Delete Operatoren Ganz normale Funktionen Template-Funktionen

35 C++11 Defaulted & Deleted Functions / 48  Deleten von New & Delete Operatoren Typ läßt sich nicht dynamisch erstellen Achtung - alle impliziten New-Varianten deleten (wenn gewollt) "delete" muß nicht deleted werden - könnte man aber machen class Type { public: static void* operator new(std::size_t) = delete; static void* operator new[](std::size_t) = delete; static void* operator new(size_t, const nothrow_t&) noexcept = delete; static void* operator new[](size_t, const nothrow_t&) noexcept = delete; }; Type* p = new Type; // Compiler-Fehler Type* q = new Type[4]; // Compiler-Fehler

36 C++11 Defaulted & Deleted Functions / 48  Ganz normale Funktionen Aber man kann auch ganz normale Funktionen deleten Dann werden z.B. beim Überladen die entsprechenden Konvertierungen unterbunden void f(double); void f(int) = delete; f(3.14); // Okay f(3); // Compiler-Fehler // -> Exakt passende Funktion mit "int" ist "deleted" // => keine Propagation zu "double"

37 C++11 Defaulted & Deleted Functions / 48  Die normale Typ-Propagation ist dadurch nicht unterbunden Double-Variante vorhanden delete auf Float-Variante => Propagation auf double, die der float nicht abfängt, werden natürlich weiterhin durchgeführt Mit Templates läßt sich das verallgemeinern => siehe nächsten Folien void f(double); void f(float) = delete; f(3.14); // Okay f(3.14f); // Compiler-Fehler f(3); // Okay - Propagation zu double

38 C++11 Defaulted & Deleted Functions / 48  Variation mit Template-Funktion Normale Funktion deleten Template-Funktion anbieten  => Nun geht jeder Typ außer dem deleteten Natürlich mit der Template-Funktion void f(double) = delete; template void f(T) {} f(3); // Okay f("C++"s); // Okay f(3.14); // Compiler-Fehler

39 C++11 Defaulted & Deleted Functions / 48  Template-Funktionen Erstellt man eine Template-Funktion und deleted sie, und überlädt sie mit einer konkreten Funktion, so kann man die Funktion nur mit dem exakten Typ aufrufen Denn alle anderen Typen würden auf die Template-Funktion zurückgreifen, und die ist deleted. void f(double); template void f(T) = delete; f(3.14); // Okay f("C++"s); // Compiler-Fehler f(3); // Compiler-Fehler

40 C++11 Defaulted & Deleted Functions / 48  Besonderheiten bei Deleted Funktionen Redundante deletes sind erlaubt Deleted Funktionen sind implizit inline Deleted Funktionen dürfen natürlich nicht nochmal definiert werden

41 C++11 Defaulted & Deleted Functions / 48  Redundante deletes sind erlaubt Daher deletes, die eigentlich nicht notwändig sind Z.B. Standard-Konstruktor explizit deleten, obwohl anderer Konstruktor da ist Der implizite wird dann ja nicht erzeugt class Type { public: Type() = delete; // Redundant, aber okay Type(int); };

42 C++11 Defaulted & Deleted Functions / 48  Deleted Funktionen sind implizit inline Daher "= delete" muß in der Klassen-Definition stehen Bei der "ersten Deklaration" Sonst wäre es eine Verletzung der ODR class Type { public: Type(); }; Type::Type() = delete; // Compiler-Fehler

43 C++11 Defaulted & Deleted Functions / 48  Deleted Funktionen dürfen nicht nochmal definiert werden "= delete" entspricht einer Defintion Würde anders ja auch keinen Sinn machen Also anders als z.B. bei rein virtuellen Funktionen mit = 0 void fct(long) = delete; void fct(long) { } // Compiler-Fehler

44 C++11 Defaulted & Deleted Functions / 48  Fazit Sie können alle Arten von Funktionen in C++11 deleten Typischerweise wird dies für die speziellen Member-Funktionen gemacht Um Klassen  nicht-kopierbar und/oder  nicht moveable und/oder  nicht dynamisch erzeugbar zu machen Außerdem kann man damit auch: Überladungs-Fehler einschränken Parameter-Propagationen verhindern Template-Instanziierungen steuern

45 C++11 Defaulted & Deleted Functions / 48 ISO & Links

46 C++11 Defaulted & Deleted Functions / 48  C++11 Standard - ISO/IEC Function definitions In general Explicitly-defaulted functions Deleted definitions 12 Special member functions 12.1 Constructors 12.4 Destructors 12.7 Construction and destruction 12.8 Copying and moving class objects 13 Overloading 13.5 Overloaded operators  Assignment

47 C++11 Defaulted & Deleted Functions / 48  Links special_member_functions special_member_functions https://www.ibm.com/developerworks/community/blogs/ f-be62- 4bc0-81c5-3956e82276f3/entry/defaulted_functions_in_c_11?lang=en https://www.ibm.com/developerworks/community/blogs/ f-be62- 4bc0-81c5-3956e82276f3/entry/defaulted_functions_in_c_11?lang=en

48 C++11 Defaulted & Deleted Functions / 48 Danke


Herunterladen ppt "C++11 Defaulted & Deleted Functions / 48 C++11 Defaulted & Deleted Functions Detlef Wilkening"

Ähnliche Präsentationen


Google-Anzeigen