Date post: | 17-Jul-2015 |
Category: |
Technology |
Upload: | holger-jakobs |
View: | 150 times |
Download: | 1 times |
kurze Geschichte von C++
● Erfinder von C++ ist BjarneStroustrup
● 1979: C with Classes● 1984: Umbenennung in C++● 1985: C++ 1.0● 1989: C++ 2.0● 1998: ISO C++● 2011: ISO C++11● 2014: ISO C++14
Haupt-Eigenschaften
● Code läuft als nativer Code direkt auf Hardware – keine virtuelle Maschine.
● Code ist typsicher (weitestgehend, Ausnahmen beruhen auf C-Kompatibilität).
● Destruktoren räumen den Speicher auf, keine Garbage Collection – denn Speicher ist nicht alles!
● Objekte werden auf dem Stack erzeugt, nicht ständig mit new auf dem Heap!
Haupt-Eigenschaften
● C++ gehört niemandem.● Es gibt eine umfangreiche Standardbibliothek,
aber ihr fehlen noch wesentliche Dinge:– GUI-Programmierung (große Auswahl vorhanden:
Qt, Tk, Gtk+, wxWidgets, … – aber kein Standard)
– XML-Bibliothek
– Unterstützung für Web-Programmierung
C++ 1.0 - 1985
Hauptsächliche Neuigkeiten:● Overloading von Funktionen/Methoden
● virtuelle Funktionen, virtual
● Referenzen als Ergänzung zu Zeigern● echte Konstanten
● Kommentare mit //
C++ 2.0 - 1989
Hauptsächliche Neuigkeiten:● Mehrfachvererbung● abstrakte Klassen● statische Methoden
● Schlüsselwort protected
ISO C++98
● STL wurde Teil der C++ Standard Library
● Deklaration von lokalen Laufvariablen in for
● Typecasts: a = double (y);
● Weglassen des .h beim #include:#include <iostream>
● Namespaces, Datentypen string bool
● stringstream statt strstream
● eine Reihe neuer Schlüsselwörter
ISO C++11
● Eigentlich war C++0x geplant …● Ziele (Stroustrup)
– Make C++ a better language for systems programming and library building
– Make C++ easier to teach and learn● Stroustrup: The range of abstractions that C++ can
express elegantly, flexibly, and at zero costs compared to hand-crafted specialized code has greatly increased.
Neuerungen in ISO C++11● Rvalues und Move Semantics● echte enum-Typen
● long long (mind. 64 bit)
● generalisierte konstante Ausdrücke constexpr
● Nullpointer nullptr
● Kontrolle durch default delete
● Typherleitung durch auto
● Initialisierung durch { … }
Neuerungen in ISO C++11● static_assert
● raw Strings● Lambda-Ausdrücke● reguläre Ausdrücke (bei g++ erst ab 4.9)
● Threads● variabel lange Parameterlisten für Templates● „smart“ pointers
● Zeitbibliothek chrono
Rvalue und Move-Semantics
● Kopierkonstruktor X(const X&);
● neu: Move-Konstruktor X(X&&);
● Zuweisung X& operator=(const X&);
● neu: Move-Zuweisung X& operator=(X&&);
● Gründe hierfür:– Speicherplatz sparen
– Performance verbessern
– Rückgabemöglichkeit ohne Zeiger
Rvalue und Move-Semantics
● siehe matrix-move.cpp
● Was man nicht machen darf: mit new neuen Speicher in operator+ holen und dann eine Referenz darauf zurückgeben.
● Grund: Wer ist für die Dereferenzierung verantwortlich? Was passiert, wenn vor der Rückgabe eine Exception geworfen wird?
● Also: Nirgendwo new machen, wo das zugehörige delete nicht dabei ist.
Rvalue und Move-Semantics
● Compiler erzeugt automatisch:– default-Konstruktor
– copy-Konstruktor und copy-Zuweisung
– move-Konstruktor und move-Zuweisung
– Destruktor
● Wenn man nur eines davon selbst definiert, fehlen die anderen!
● Lösung (hier am Beispiel des move-Konstruktors):X(X&&) = default;
Rvalue und Move-Semantics
● Woher weiß der Compiler, ob er move oder copy machen soll?
● Bei Werterückgaben weiß er das.
● sonst Hinweis geben mit std::move(x);template <typename T>void swap (T &a, T &b) { T tmp = std::move(a); a = std::move(b); b = std::move(tmp);}
Consider how to return a potentially large number of elements from a function. Here is a conventional C++98 function returning the indices of string matches:
vector<int>* find_all (vector<string>& vs, const string& s) { vector<int>* res = new vector<int>; for (int i = 0; i < vs->size(); ++i) if (vs[i] == s) res->push_back(i); return res;}
vector<int>* pvi = find_all(some_vec,"vindaloo");for (vector<int>::iterator p = pvi->begin(); p!=pvi->end(); ++p) cout << *p << " is a match\n"; // …delete pvi;
Quelle: http://www.informit.com/articles/article.aspx?p=2080042
sonst: memory leak!
Move semantics allows a significant simplification:
vector<int> find_all(vector<string>& vs, const string& s) { vector<int> res; for (int i = 0; i<vs.size(); ++i) if (vs[i] == s) res.push_back(i); return res;}
for (int x: find_all(some_vec,"vindaloo")) cout << x << " is a match\n";
Auch die Wiedergabe ist viele einfacher!
Natürlich kann es auch kein Memory Leak geben, denn es muss nichts mit delete freigegeben werden.
move-Semantik
unique_ptr und shared_ptr
● unique_ptr kann nicht kopiert werden.
● Ihm gehört der Speicher, auf den er zeigt. ● Geht er out of scope, gibt er den Speicher frei.● Eigentümerschaft kann übertragen werden.
● shared_ptr kann mehrere Eigentümer haben.
● Er hat einen Referenzzähler.● Geht der Zähler auf 0, wird der Speicher
freigegeben.
weak_ptr
● weak_ptr zeigt auf einen shared_ptr
● Referenzzähler wird für weak_ptr nicht hochgezählt.
● Daher kann das Objekt auch jederzeit gelöscht werden.
● Vor Zugriff muss er in einen shared_ptr umgewandelt werden mittels lock()
Was sollten C-Programmierer sofort vergessen?
Eigentlich alles, was Stress macht bzw. gefährlich ist (buffer overflow):
● Zeichenketten à la C, also char[] und char*,stattdessen string verwenden!
● Alle Arrays, stattdessen Standardcontainer verwenden: array vector list deque forward_list set map
● C-I/O wie printf() fprintf() fgets(), stattdessen iostream verwenden.
● Zeiger zur Parameterübergabe oder Wertrückgabe, stattdessen const& und Move-Semantik verwenden
Neu in C++14
C++14 ist nur ein Finetuning, nicht vergleichbar mit C++11
void sort(Container& c);vector<string> vs {"Hello", "new", "World"};sort(vs); // fine: vs is a Container
template<Sortable Cont>void sort(Cont& container);vector<double> vec {1.2, 4.5, 0.5, -1.2};list<int> lst {1, 3, 5, 4, 6, 8,2};sort(vec); // OK: a vector is Sortablesort(lst); // Error at (this) point of use: // Sortable requires random access
Neu in C++14template<class T>constexpr T pi = T(3.1415926535897932385);
//C++14, a variable template in usetemplate<typename T>T circular_area(T r) { return pi<T> * r * r;}
double darea = circular_area(5.5);//uses pi<double>
float farea = circular_area(5.5f);//uses pi<float>
Template-Variablen sind nicht auf eingebaute Typen beschränkt. matrix<T>, complex<T> usw. gehen auch.