Praxisorientierte Einführung in C++ Lektion: "Smart-Pointer"

Ähnliche Dokumente
Praxisorientierte Einführung in C++ Lektion: "Dynamische Speicherverwaltung"

Praxisorientierte Einführung in C++ Lektion: "Das Schlüsselwort explicit"

Verschlüsseln eines Bildes. Visuelle Kryptographie. Verschlüsseln eines Bildes. Verschlüsseln eines Bildes

DAP2-Programmierpraktikum Einführung in C++ (Teil 2)

Vorkurs C++ Programmierung

5. Behälter und Iteratoren. Programmieren in C++ Überblick. 5.1 Einleitung. Programmieren in C++ Überblick: 5. Behälter und Iteratoren

Programmieren 2 C++ Überblick

Dynamische Datentypen

Einführung in die Programmierung mit C++

Crashkurs C++ - Teil 1

Praxisorientierte Einführung in C++ Lektion: "Die Compiler-Chain (Vom Quellcode zum ausführbaren Programm)"

C++ Teil 5. Sven Groß. 13. Mai Sven Groß (IGPM, RWTH Aachen) C++ Teil Mai / 18

Grundkurs C++ IDE Klassenhierarchien

Praxisorientierte Einführung in C++ Lektion: "Operatoren"

Universität Hamburg. Seminar: Effiziente Programmierung in C. Referenzzählung. Autoren: Kevin Köster. Betreuer: Michael Kuhn

Grundkurs C++ IDE Klassenhierarchien

C++ - Objektorientierte Programmierung Konstante und statische Elemente

Advanced Programming in C

Praxisorientierte Einführung in C++ Lektion: "Exceptions"

C++ Teil 6. Sven Groß. 27. Mai Sven Groß (IGPM, RWTH Aachen) C++ Teil Mai / 14

C A R L V O N O S S I E T Z K Y. Boost C++ Libraries. Johannes Diemke. Department of Computer Science Learning and Cognitive Systems

Verkettete Datenstrukturen: Listen

Grundlagen Polymorphismus Eigenschaften virtueller Klassen Mehrfachvererbung bei ROOT. Mehrfache Vererbung. Daniel Beneckenstein. 21.

Programmierung mit C Zeiger

Felder (Arrays) und Zeiger (Pointers) - Teil I

Programmierkurs C/C++

Modernes C++ Compilation Firewall Exception-Safe Function Calls. Philippe Lieser

Algorithmen und Datenstrukturen

Heap vs. Stack vs. statisch. 6 Speicherorganisation. Beispiel Statische Variablen. Statische Variablen

C++ Teil 5. Sven Groß. 8. Mai IGPM, RWTH Aachen. Sven Groß (IGPM, RWTH Aachen) C++ Teil 5 8. Mai / 16

Einführung in die Programmierung zusammengesetzte Datentypen, dynamischer Speicher

C-Pointer (Zeiger, Adressen) vs. C++ Referenzen

Heap vs. Stack vs. statisch. 6 Speicherorganisation. Beispiel Statische Variablen. Statische Variablen

Objektorientierte Programmierung mit C++ Vector und List

Intelligente Zeiger 283

Praxisorientierte Einführung in C++ Lektion: "Kontrollstrukturen"

6 Speicherorganisation

Überblick. Überblick. Abstrakte Klassen - rein virtuelle Funktionen Beispiele

Objektorientierte Programmierung mit C++ den sog. default constructor X (){}

Zeiger und dynamischer Speicher

Wichtige Prinzipien von C#

C++ Klassen, Vererbung. Philipp Lucas. Sebastian Hack. Wintersemester 2008/09. saarland.

Betriebssysteme, Rechnernetze und verteilte Systeme 1. Crashkurs C (2)

Alltagsnotizen eines Softwareentwicklers

7. Übung Informatik II - Objektorientierte Programmierung

Institut für Programmierung und Reaktive Systeme. Java 6. Markus Reschke

Programmiertechnik. Teil 4. C++ Funktionen: Prototypen Overloading Parameter. C++ Funktionen: Eigenschaften

Einführung in die Programmiersprache C

Felder (Arrays) und Zeiger (Pointers) - Teil I

Einführung in C# Teil 1. Matthias Nübling

Einführung in die Programmiersprache C

C++ Teil 9. Sven Groß. 17. Juni Sven Groß (IGPM, RWTH Aachen) C++ Teil Juni / 17

Von der UML nach C++

Java I Vorlesung 6 Referenz-Datentypen

C++ Notnagel. Ziel, Inhalt. Programmieren in C++

Probeklausur: Programmierung WS04/05

Konstruktor/Destruktor

CORBA Implementierung von Client und Server

Vorkurs Informatik: Erste Schritte der Programmierung mit C++

Programmieren in C++ Überladen von Methoden und Operatoren

Objektorientierte Programmierung Studiengang Medieninformatik

Fragen zur OOP in Java

Vorkurs Informatik: Erste Schritte der Programmierung mit C++

11 Vererbung und Klassenhierarchie

AuD-Tafelübung T-B5b

Wo und wie lange leben Objekte? globale Objekte lokale Objekte dynamische Objekte

C++ Templates. Wozu Templates? Definition von Templates. Gebrauch von Templates. Instanziierung und Organisation

Crashkurs C++ Wiederholung

C++-Zusammenfassung. H. Schaudt. August 18, 2005

Themen. Statische Methoden inline Methoden const Methoden this Zeiger Destruktor Kopierkonstruktor Überladen von Operatoren

3 Klassen, Attribute, Methoden

II.4.5 Generische Datentypen - 1 -

Objektorientierung (OO)

einlesen n > 0? Ausgabe Negative Zahl

C++ - Objektorientierte Programmierung Konstruktoren und Destruktoren

Einstieg in die Informatik mit Java

Gobales Gedächtnis. AntMe. Sebastian Loers. lb-sys.info. Projekt: AntMe - Globales Gedächtnis (Version 1.0)

Transkript:

Praxisorientierte Einführung in C++ Lektion: "Smart-Pointer" Christof Elbrechter Neuroinformatics Group, CITEC June 26, 2014 Christof Elbrechter Praxisorientierte Einführung in C++ June 26, 2014 1 / 17

Table of Contents C++-Speicher-Management Smart-Pointer in C++ Schema: Smart-Pointer Exkurs Operatoren '*' und '->' Implementation Anwendungsbeispiel Bermerkungen C++-11 Christof Elbrechter Praxisorientierte Einführung in C++ June 26, 2014 2 / 17

C++-Speicher-Management Nachteile des Speicher-Managements in C++ Wie bereits oft gesehen: C++-Pointer bringen nicht nur Vorteile mit sich Speicher muss explizit mit new oder new [] alloziert werden Speicher muss immer irgendwann explizit mit delete oder delete [] freigegeben werden Man darf mit- und ohne []-Klammern Versionen nicht verwechseln/mischen Gefahr für Speicherlecks Manchmal ist nicht klar, wer ein Objekt Freigeben muss struct Button{ void add(actionlistener listener); // Ownership //... }; Dabei ist der minimale Overhead eines managed-pointers meiÿt zu vertreten Christof Elbrechter Praxisorientierte Einführung in C++ June 26, 2014 3 / 17

C++-Speicher-Management Nachteile des Speicher-Managements in C++ Gleiches Problem entsteht, falls Funktionen Pointer zurückgeben/erzeugen struct ImageReader{ Image grabnextimage (); //... }; Wem gehört das zurückgegebene Bild? Darf man es verändern? (OK: const-hint) Muss man es freigeben? Ownership muss eindeutig in der Dokumentation geklärt werden Ansonsten besteht die Gefahr für Speicherlecks (delete-aufruf zu wenig) Seg.-Faults (delete Aufruf zu viel) Gröÿtes Problem: Dokumentation des Verhaltens ist beliebig und kein eigentliches Sprachkonstrukt Christof Elbrechter Praxisorientierte Einführung in C++ June 26, 2014 4 / 17

Smart-Pointer in C++ Smart-Pointer in C++ Auch können oft nicht einfach Objekte übergeben/zurückgegeben werden Groÿer Aufwand für tiefe Kopien Vererbung und virtuelle Funktionen funktionieren nicht Ein Ausweg für all diese Probleme bieten sog. intelligente Pointer (Smart-Pointer) Aber Smart-Pointer sind keine spezielles Sprachkonstrukte Leider innerhalb der C++-Standard-Bibliothek keine vernünftige Implementation vorhanden Aber glücklicherweise generische Implementation mittels Template relativ simpel Christof Elbrechter Praxisorientierte Einführung in C++ June 26, 2014 5 / 17

Smart-Pointer in C++ Smart-Pointer in C++ Das SmartPtr Objekt kann Java-like verwendet werden (Ohne & und ohne *) Intern wird ein Referenzzähler verwendet, um zu ermitteln, wann der letzte SmartPtr für einen bestimmten Daten-Pointer verloren geht Wenn die letzte Referenz gelöscht wird, wird auch der Speicher auf dem Heap wieder freigegeben Da Smart-Pointer intern einen Pointer wrappen, funktionieren auch Vererbung und virtuelle Funktionen damit wie erwartet Christof Elbrechter Praxisorientierte Einführung in C++ June 26, 2014 6 / 17

Schema: Smart-Pointer SmartPtr Step-by-Step SmartPtr A Daten-Pointer Referenz-Zähler Heap Objekt Referenz-Zähler: 1 Anstatt direkt mit dem Pointer auf einen bestimmten Typ zu arbeiten: Arbeite mit Objekten einer Smart-Pointer-Klasse Schema Christof Elbrechter Praxisorientierte Einführung in C++ June 26, 2014 7 / 17

Schema: Smart-Pointer SmartPtr Step-by-Step SmartPtr A Daten-Pointer Referenz-Zähler Heap Objekt Referenz-Zähler: 1 Ein einfaches SmartPtr-Objekt, welches derzeit die einzige Referenz auf ein bestimmtes Datum darstellt SmartPtr A(new X); Referenz-Zähler ist 1 Christof Elbrechter Praxisorientierte Einführung in C++ June 26, 2014 7 / 17

Schema: Smart-Pointer SmartPtr Step-by-Step Heap Kopie des SmartPtrs erstellen SmartPtr A Daten-Pointer Referenz-Zähler SmartPtr B Daten-Pointer Referenz-Zähler Objekt Referenz-Zähler: 2 SmartPtr B = A; Referenz-Zähler wird inkrementiert Nicht das Datum, sondern der Pointer darauf wird kopiert Christof Elbrechter Praxisorientierte Einführung in C++ June 26, 2014 7 / 17

Schema: Smart-Pointer SmartPtr Step-by-Step SmartPtr A Daten-Pointer Referenz-Zähler SmartPtr B Daten-Pointer Referenz-Zähler Heap Objekt Referenz-Zähler: 1 Falls irgendeine Referenz verloren geht, wird Referenz-Zähler dekrementiert Nur wenn der Referenz-Zähler 0 wird, wird auch das Datum gelöscht Hier: Referenz-Zähler ist immer noch 1 nichts wird gelöscht Christof Elbrechter Praxisorientierte Einführung in C++ June 26, 2014 7 / 17

Schema: Smart-Pointer SmartPtr Step-by-Step SmartPtr A Daten-Pointer Referenz-Zähler Heap Objekt Referenz-Zähler: 1 Falls jedoch auch die letzte Referenz verloren geht, wird der das Objekt freigegeben SmartPtr B Daten-Pointer Referenz-Zähler Auch der Speicher für den Referenzzähler muss freigegeben werden Christof Elbrechter Praxisorientierte Einführung in C++ June 26, 2014 7 / 17

Schema: Smart-Pointer SmartPtr Step-by-Step SmartPtr A Daten-Pointer Referenz-Zähler Heap Objekt Referenz-Zähler: 0 Falls jedoch auch die letzte Referenz verloren geht, wird der das Objekt freigegeben SmartPtr B Daten-Pointer Referenz-Zähler Auch der Speicher für den Referenzzähler muss freigegeben werden Christof Elbrechter Praxisorientierte Einführung in C++ June 26, 2014 7 / 17

Schema: Smart-Pointer SmartPointer Implementation Es existiert eine Vielzahl von Implementationen von Smart-Pointer Klassen Besonders prominent: boost::shared_ptr 1 I.d.R. realisiert durch generisches Klassen-Template SmartPtr.h tempate<class T> class SmartPtr{ //... }; 1 http://www.boost.org/ Christof Elbrechter Praxisorientierte Einführung in C++ June 26, 2014 8 / 17

Exkurs Operatoren '*' und '->' Exkurs: Pointer- und Dereferenz-Operator In der Lektion Operatoren wurden diese ausgelassen, da sie ohne Eine Klasse wie SmartPointer relativ umbrauchbar sind und selten verwendet werden Dereferenzierungsoperator: operator*() Zeigeroperator: operator->() Damit: Klassen, die sich ein wenig wie Zeiger verhalten Beispiel struct X { int i; }; struct WannaBePointerToX { X m x ; X operator >() { return & m x ; } X& operator () { return m x ; } }; int main() { WannaBePointerToX x; x >i = 1; std::cout << ( x).i << std::endl; } Christof Elbrechter Praxisorientierte Einführung in C++ June 26, 2014 9 / 17

Exkurs Operatoren '*' und '->' Fokus: Zeiger-Operator Warum muss man -> nicht zweimal verwenden (x->->i)? int main() { WannaBePointerToX x; x >i = 1; } Pointe-Operator Wenn Klasse X den operator->() deniert, dann wird bei Zugri über diesen Operator auf dem Rückgabewert aufgerufen Solange, bis echter Pointer zurückgegeben wird Christof Elbrechter Praxisorientierte Einführung in C++ June 26, 2014 10 / 17

Exkurs Operatoren '*' und '->' Proof-of-concept struct X { int i; }; struct WannaBePointerToX { X m x ; X operator >() { return & m x ; } }; struct WannaBePointerToPointerToX { WannaBePointerToX m x ; WannaBePointerToX operator >() { return m x ; } }; int main() { WannaBePointerToPointerToX x; x >i = 1; } Christof Elbrechter Praxisorientierte Einführung in C++ June 26, 2014 11 / 17

Implementation Eine SmartPtr Implementation Eine spezielle Implementation wird hier nun vorgestellt Vereinfachte Version des boost::shared_ptr Klassen-Templates Diese funktioniert nur mit Objekten auf dem Heap nicht mit Arrays (da delete und nicht delete []) verwendet wird Ist aber leicht erweiterbar Komplette Implem. in einem Header Christof Elbrechter Praxisorientierte Einführung in C++ June 26, 2014 12 / 17

Implementation Eine SmartPtr Implementation SmartPtr.h template<class T> class SmartPtr{ T elem; // Daten Pointer int refc; // Referenzzaehler void inc(); // Eine Referenz mehr void dec(); // Eine Referenz weniger public: SmartPtr(): elem(0),refc(0){} SmartPtr(T data): elem(data), refc(data?new int(1):0){} SmartPtr(const SmartPtr &o): elem(0),refc(0){ this = o; } SmartPtr &operator=(const SmartPtr& o); SmartPtr(){ dec(); } T &operator () { return elem; } const T &operator () const { return elem; } T get () { return elem; } const T get () const { return elem; } T operator > () { return elem; } const T operator > () const { return elem; } operator bool() const { return!!elem; } }; Christof Elbrechter Praxisorientierte Einführung in C++ June 26, 2014 13 / 17

Implementation Eine SmartPtr Implementation template<class T> SmartPtr<T> &SmartPtr<T>::operator=( const SmartPtr<T>& o){ if(o.elem == elem) return this; // Selbstzuweisung dec(); // dekrementiere Referenzzaehler fuer aktuelles Objekt. Loesche // das Objekt und den aktuellen Referenzzaehler falls notwendig elem = o.elem; // kopiere Daten refc = o.refc; inc(); // this ist neue Referenz auf elem // > inkrementiere Referenzzaehler return this; } template<class T> void SmartPtr<T>::inc() { // Falls refc und elem nicht if(refc) ( refc)++; // 0 sind: erhoehe Referenz Zaehler } template<class T> void SmartPtr<T>::dec() { if(!refc) return; // tue nichts falls refc 0 ist if( ( ( refc)) == 0){ // dekrementiere refc delete elem; // falls nun 0: loesche elem und refc delete refc; } } Christof Elbrechter Praxisorientierte Einführung in C++ June 26, 2014 14 / 17

Anwendungsbeispiel Anwendungsbeispiel struct Rect { int x,y,w,h, }; // relativ gaengig: Ptr Postfix typedef SmartPtr<Rect> RectPtr; int main(){ RectPtr p1(new Rect); RectPtr p2; p1 = p2; p1 = p1 = p2 = p2 = RectPtr(new Rect); p1 = RectPtr(new Rect); p1 = RectPtr (0); if(p1){ p1 >x = p1 >y; // Direkter Zugriff auf die Member } if(p1) p1.get() >w = 7; // Zugriff via Daten Pointer } if(p1 && p2) p1 = p2; // Zugriff auf Objekte als Referenz Christof Elbrechter Praxisorientierte Einführung in C++ June 26, 2014 15 / 17

Bermerkungen Bermerkungen Smart-Pointer: Gutes Konzept gegen Memory-Leaks Nur verwenden falls sinnvoll Für sehr kleine Objekte (z.b. struct Point{int x,y;}) besser direkt mit Objekten arbeiten Vor allem für Objekte, die viele Resourcen benötigen Es existiert eine etwas schwächere Implementation in der STL im header <memory>: die template-klasse std::auto_ptr std::auto_ptr: kein Referenz-Zähler Ownership wird bei jeder Zuweisung und jedem Konstruktor-Aufruf an den lvalue übergeben Exception-safe-Programming: Hier sind Smart-Pointer besonders interessant std::auto_ptr sind aber auch ausreichend wird in der Lektion Exceptions noch mal aufgegrien Christof Elbrechter Praxisorientierte Einführung in C++ June 26, 2014 16 / 17

C++-11 C++-11 Im Header memory ist dann auch ein std::shared_ptr<t> Klassentemplate Equivalent zu boost's shared_ptr<t> template Zusätzlich hier: std::weak_ptr<t> Ähnelt dem Konzept des shared pointers ihm gehört das Objekt aber nicht Ist er die einzige Referenz auf ein Objekt, so wird dieses zerstört Für den Zugri auf das dahinterliegende Objekt, wird temporär ein std::shared_ptr erstellt Dieser ist dann entweder NULL oder er ist gültig, so lange er existiert und std::unique_ptr, welcher nicht kopiert werden kann wird oft für Sigeltons und so verwendet Christof Elbrechter Praxisorientierte Einführung in C++ June 26, 2014 17 / 17