int main(){ int main(){ Das wollen wir doch genau verstehen! std::vector<int> v(10,0); // Vector of length 10

Ähnliche Dokumente
Wörterbuch, Selbstandornung, Implementation Wörterbuch mit Array / Liste / Skipliste. [Ottman/Widmayer, Kap. 3.3,1.7, Cormen et al, Kap.

Wörterbuch (Dictionary)

Visuelle Kryptographie. Anwendung von Zufallszahlen

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

Programmieren in C++ Überblick

variadic templates Templates mit variabler Argumentanzahl?

Programmieren 2 C++ Überblick

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

Dynamische Datentypen

Einführung zu den Klassen in C++ 107

Konstruktor & Destruktor

C++11. neu in C++11: range-based for. Objektorientierte Programmierung mit C++ Ersetzung durch: 1. Elementares C++ int array[] = { 1, 2, 3, 4, 5 };

Praxisorientierte Einführung in C++ Lektion: "Der C++-11 Standard"

Programmieren in C++ Überladen von Methoden und Operatoren

Modernes C++ (C++11)

Structs, Referenztypen und Const-Typen

Initialisierung vs. Zuweisung:

Lambda-Funktionen. Lambda-Funktionen. Lambda-Funktionen sollen

Programmierkurs C/C++

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

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

Was Mathematiker schon vor Jahrhunderten erfunden haben, gibt es jetzt endlich in ihrer Programmiersprache:

Lindenmayer-Systeme: Fraktale rekursiv zeichnen

Systemnahe Programmierung in C/C++

C++ - Container und dynamische Speicherverwaltung

C++ Kurs Teil 3. Standard Template Library (STL) Kommunikation mit der shell Hyper Text Markup Language (HTML)

Polymorphismus 179. Function.h. #include <string>

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

18. Vererbung und Polymorphie

Objektorientierte Programmierung mit C++ SS 2007

Lindenmayer-Systeme: Fraktale rekursiv zeichnen. Definition. Definition. Definition. o Alphabet Σ ( Beispiel: {F, +, -} )

Grundlagen C und C++ Einheit 04: Weitere Grundlagen in C++ Lorenz Schauer Lehrstuhl für Mobile und Verteilte Systeme

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

Einführung in C++ Operatoren überladen (Klassen)

Schriftlicher Test (120 Minuten) VU Einführung ins Programmieren für TM. 25. Jänner 2016

1. Zeiger, Algorithmen, Iteratoren und Container. Felder als Funktionsargumente, Zeiger, Iteratoren auf Vektoren, Container

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

Crashkurs C++ Wiederholung

Java I Vorlesung 6 Referenz-Datentypen

Problem: Vererbung erlaubt die Wiederverwendung d von Programmcode, virtuelle Funktionen ermöglichen dabei den Austausch gewisser Funktionalität

19. STL Container Programmieren / Algorithmen und Datenstrukturen 2

Grundlagen der Programmiersprache C für Studierende der Naturwissenschaften

virtual Wertpapier& operator=(const Wertpapier&); // VIRTUELLE ZUWEISUNG protected: static enum {wortfeldlaenge = 20}; char* name_z; double kurs; };

13. C++ vertieft (III): Funktoren und Lambda

Coding Conventions. for C++ Reto Carrara Gyrenstrasse 17 CH-8967 Widen +4179/

18. Vererbung und Polymorphie

C++ - Objektorientierte Programmierung Konstruktoren und Destruktoren

Objektorientierte Programmierung mit C++ Vector und List

Objektorientierte Programmierung mit C++ Sonderfälle. empfohlene Variante. alle einstelligen

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

19. Vererbung und Polymorphie

Einführung in die Informatik: Programmierung und Software-Entwicklung, WS 11/12 1. Kapitel 11. Listen. Listen

Hier wird die Verwendung der Standard Template Library (kurz STL) kurz beschrieben. Inhalt 1.Verwendung der STL Grundlagen...

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

Einführung in die Informatik: Programmierung und Software-Entwicklung, WS 16/17. Kapitel 13. Listen. Listen 1

Einführung in die Informatik: Programmierung und Software-Entwicklung, WS 15/16. Kapitel 12. Listen. Listen 1

Programmier-Befehle - Woche 8

Java vs. C++: Different by Design

Intelligente Zeiger 283

Semantics of C++ Seminar Wintersemester 2009/2010. RValue-Referenzen. Martin Sevenich. 6. Dezember 2009

Einführung in objektorientiertes Programmieren. Karl Gmeiner

Programmierkurs. SoSe Markus Geveler Inst. f. Applied Mathematics, TU Dortmund.

Überladen von Operatoren

Programmieren I. Arrays Heusch 7.2 Ratz Institut für Angewandte Informatik

Programmierkurs C++ Templates & STL (1/2)

7.0 Arbeiten mit Objekten und Klassen

Abgeleitete Datentypen

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

Programmier-Befehle - Woche 10

Verwendung von Klassen in C++

5. Abgeleitete Datentypen

Kurze Einführung in die Programmiersprache C++ und in Root

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

Pods und Objects (Klassen)

const Zwei Schlüsselwörter bei der Deklaration von Variablen und Member-Funktionen haben wir noch nicht behandelt: const und static.

Informatik I (D-MAVT)

Java Tools JDK. IDEs. Downloads. Eclipse. IntelliJ. NetBeans. Java SE 8 Java SE 8 Documentation

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

Programmieren - C++ Templates

Objektorientierte Programmierung mit C++

Lösung der OOP-Prüfung WS12/13

Prozesse und Threads. wissen leben WWU Münster

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

C++ Teil 12. Sven Groß. 18. Jan Sven Groß (IGPM, RWTH Aachen) C++ Teil Jan / 11

Javakurs 2013 Objektorientierung

13. C++ vertieft (III): Funktoren und Lambda

1.5. Strukturierte Anweisungen

! Es ist nicht möglich, neue Operatoren einzuführen (**

15. C++ vertieft (IV): Ausnahmen (Exceptions)

Die erste C++ Funktion

C++: Klassen mit Wertsemantik. C++: Klassen mit Wertsemantik. The Rule of Three. Nachtrag: friends

Lambda-Ausdrücke in Programmiersprachen 76

kurze Wiederholung class templates

Metaprogrammierung 372

Probeklausur. Klausurdeckblatt. Name der Prüfung: Objekt-orientierte Programmierung mit C++

Einführung in die STL anhand eines ausgewählten Beispiels

Mapra: C++ Teil 2. Felix Gruber, Sven Groß. 2. Mai 2017 IGPM. Felix Gruber, Sven Groß (IGPM) Mapra: C++ Teil 2 2. Mai / 11

Transkript:

Wir erinnern uns #include <iostream> #include <vector> 6. C++ vertieft (I) Kurzwiederholung: Vektoren, Zeiger und Iteratoren Bereichsbasiertes for, Schlüsselwort auto, eine Klasse für Vektoren, Subskript-Operator, Move-Konstruktion, Iterator. Das wollen wir doch genau verstehen! // Vector of length 10 std::vector<int> v(10,0); // Input for (int i = 0; i < v.length(); ++i) std::cin >> v[i]; // Output for (std::vector::iterator it = v.begin(); it!= v.end(); ++it) std::cout << it << " "; Und zumindest das scheint uns zu umständlich! 165 166 Nützliche Tools (1): auto (C++11) Das Schlüsselwort auto: Der Typ einer Variablen wird inferiert vom Initialisierer. Beispiele int x = 10; auto y = x; // int auto z = 3; // int std::vector<double> v(5); auto i = v[3]; // double Etwas besser #include <iostream> #include <vector> std::vector<int> v(10,0); // Vector of length 10 for (int i = 0; i < v.length(); ++i) std::cin >> v[i]; for (auto it = x.begin(); it!= x.end(); ++it){ std::cout << it << " "; 167 168

Nützliche Tools (2): Bereichsbasiertes for (C++11) for (range-declaration : range-expression) statement; range-declaration: benannte Variable vom Elementtyp der durch range-expression spezifizierten Folge. range-expression: Ausdruck, der eine Folge von Elementen repräsentiert via Iterator-Paar begin(), end() oder in Form einer Initialisierungsliste. Beispiele Ok, das ist cool! #include <iostream> #include <vector> std::vector<int> v(10,0); // Vector of length 10 for (auto& x: v) std::cin >> x; std::vector<double> v(5); for (double x: v) std::cout << x; // 00000 for (int x: {1,2,5) std::cout << x; // 125 for (double& x: v) x=5; for (const auto i: x) std::cout << i << " "; 169 170 Für unser genaues Verständis Wir bauen selbst eine Vektorklasse, die so etwas kann! Auf dem Weg lernen wir etwas über RAII (Resource Acquisition is Initialization) und Move-Konstruktion Index-Operatoren und andere Nützlichkeiten Templates Exception Handling Funktoren und Lambda-Ausdrücke Eine Klasse für Vektoren int size; double elem; public: // constructors vector(): size{0, elem{nullptr {; vector(int s):size{s, elem{new double[s] { // destructor ~vector(){ delete[] elem; // something is missing here 171 172

Elementzugriffe Was läuft schief? // getter. pre: 0 <= i < size; double get(int i) const{ return elem[i]; // setter. pre: 0 <= i < size; void set(int i, double d){ // setter elem[i] = d; // length property int length() const { return size; ~ double get( int i ) const; 173 vector v(32); for (int i = 0; i<v.length(); ++i) v.set(i,i); vector w = v; for (int i = 0; i<w.length(); ++i) w.set(i,i i); return 0; ~ double get( int i ); *** Error in vector1 : double free or corruption (!prev): 0x0000000000d23c20 *** ======= Backtrace: ========= /lib/x86_64-linux-gnu/libc.so.6(+0x777e5)[0x7fe5a5ac97e5] 174 Rule of Three! Rule of Three! public: // Copy constructor vector(const vector &v): size{v.size, elem{new double[v.size] { std::copy(v.elem, v.elem+v.size, elem); ~ double get( int i ); // Assignment operator vector& operator=(const vector&v){ if (v.elem == elem) return this; if (elem!= nullptr) delete[] elem; size = v.size; elem = new double[size]; std::copy(v.elem, v.elem+v.size, elem); return this; ~ double get( int i ); Jetzt ist es zumindest korrekt. Aber umständlich. 175 176

Eleganter geht so: // Assignment operator vector& operator= (const vector&v){ vector cpy(v); swap(cpy); return this; private: // helper function void swap(vector& v){ std::swap(size, v.size); std::swap(elem, v.elem); ~ double get( int i ); 177 Arbeit an der Fassade. Getter und Setter unschön. Wir wollen einen Indexoperator. Überladen! So? double operator[] (int pos) const{ return elem[pos]; void operator[] (int pos, double value){ elem[pos] = double; Nein! 178 Referenztypen! // for const objects double operator[] (int pos) const{ return elem[pos]; // for non const objects double& operator[] (int pos){ return elem[pos]; // return by reference! ~ Soweit, so gut. vector v(32); // Constructor for (int i = 0; i<v.length(); ++i) v[i] = i; // Index Operator (Referenz!) vector w = v; // Copy Constructor for (int i = 0; i<w.length(); ++i) w[i] = i i; ~ const auto u = w; for (int i = 0; i<u.length(); ++i) std::cout << v[i] << ":" << u[i] << " "; // 0:0 1:1 2:4 return 0; 179 180

Anzahl Kopien Wie oft wird v kopiert? vector operator+ (const vector& l, double r){ vector result (l); // Kopie von l nach result for (int i = 0; i < l.length(); ++i) result[i] = l[i] + r; return result; // Dekonstruktion von result nach Zuweisung vector v(16); // Allokation von elems[16] v = v + 1; // Kopie bei Zuweisung! return 0; // Dekonstruktion von v Move-Konstruktor und Move-Zuweisung // move constructor vector (vector&& v): size(0), elem{nullptr{ swap(v); ; // move assignment vector& operator=(vector&& v){ swap(v); return this; ; ~ vector (vector&& v); vector& operator=(vector&& v); v wird zwei Mal kopiert. 181 182 Erklärung Illustration zur Move-Semantik Wenn das Quellobjekt einer Zuweisung direkt nach der Zuweisung nicht weiter existiert, dann kann der Compiler den Move-Zuweisungsoperator anstelle des Zuweisungsoperators einsetzen. 3 Damit wird eine potentiell teure Kopie vermieden. Anzahl der Kopien im vorigen Beispiel reduziert sich zu 1. // nonsense implementation of a "vector" for demonstration purposes class vec{ public: vec () { std::cout << "\n"; vec (const vec&) { std::cout << "\n"; vec& operator = (const vec&) { std::cout << "copy assignment\n"; return this; ~vec() { ; 3 Analoges gilt für den Kopier-Konstruktor und den Move-Konstruktor. 183 184

Wie viele Kopien? vec operator + (const vec& a, const vec& b){ vec tmp = a; // add b to tmp return tmp; f = f + f + f + f; copy assignment 4 Kopien des Vektors Illustration der Move-Semantik // nonsense implementation of a "vector" for demonstration purposes class vec{ public: vec () { std::cout << "\n"; vec (const vec&) { std::cout << "\n"; vec& operator = (const vec&) { std::cout << "copy assignment\n"; return this; ~vec() { // new: move constructor and assignment vec (vec&&) { std::cout << "move constructor\n"; vec& operator = (vec&&) { std::cout << "move assignment\n"; return this; ; 185 186 Wie viele Kopien? vec operator + (const vec& a, const vec& b){ vec tmp = a; // add b to tmp return tmp; f = f + f + f + f; move assignment 3 Kopien des Vektors Wie viele Kopien? vec operator + (vec a, const vec& b){ // add b to a return a; f = f + f + f + f; move constructor move constructor move constructor move assignment 1 Kopie des Vektors Erklärung: Move-Semantik kommt zum Einsatz, wenn ein x-wert (expired) zugewiesen wird. R-Wert-Rückgaben von Funktionen sind x-werte. 187 http://en.cppreference.com/w/cpp/language/value_category 188

Wie viele Kopien void swap(vec& a, vec& b){ vec tmp = a; a=b; b=tmp; vec g; swap(f,g); copy assignment copy assignment 3 Kopien des Vektors X-Werte erzwingen void swap(vec& a, vec& b){ vec tmp = std::move(a); a=std::move(b); b=std::move(tmp); vec g; swap(f,g); move constructor move assignment move assignment 0 Kopien des Vektors Erklärung: Mit std::move kann man einen L-Wert Ausdruck zu einem X-Wert (genauer: zu einer R-Wert Referenz) machen. Dann kommt wieder Move-Semantik zum Einsatz. http://en.cppreference.com/w/cpp/utility/move 189 190 Bereichsbasiertes for Iterator für den Vektor Wir wollten doch das: vector v = ; for (auto x: v) std::cout << x << " "; Dafür müssen wir einen Iterator über begin und end bereitstellen. // Iterator double begin(){ return elem; double end(){ return elem+size; ~ vector (vector&& v); vector& operator=(vector&& v); double begin(); double end(); 191 192

Const Iterator für den Vektor Zwischenstand // Const Iterator const double begin() const{ return elem; const double end() const{ return elem+size; ~ vector (vector&& v); vector& operator=(vector&& v); double begin(); double end(); const double begin() const; const double end() const; 193 vector Natural(int from, int to){ vector v(to from+1); for (auto& x: v) x = from++; return v; vector v = Natural(5,12); for (auto x: v) std::cout << x << " "; // 5 6 7 8 9 10 11 12 std::cout << "\n"; std::cout << "sum=" << std::accumulate(v.begin(), v.end(),0); // sum = 68 return 0; 194 Nützliche Tools (3): using (C++11) using ersetzt in C++11 das alte typedef. Beispiel using identifier = type id; using element_t = double; std::size_t size; element_t elem; 195