Praxisorientierte Einführung in C++ Lektion: "Der C++-11 Standard" Christof Elbrechter Neuroinformatics Group, CITEC July 5, 2012 Christof Elbrechter Praxisorientierte Einführung in C++ July 5, 2012 1 / 20
Table of Contents Allgemeines Move Semantics constexpr keyword std::initializer_list Einheitliche Initialisierung Das neue auto Keyword Range-based for Konstruktoren Weitere Sachen STL Erweiterungen Christof Elbrechter Praxisorientierte Einführung in C++ July 5, 2012 2 / 20
Allgemeines Allgemeines Eigentlich als C++-0x Standard geplant Kam leider erst 2011 Bringt neue Features ist aber zu 99% abwärtskompatibel Alter Standard: C++-03 neuer Standard: C++-11 Christof Elbrechter Praxisorientierte Einführung in C++ July 5, 2012 3 / 20
Move-Semantics mit RValue-References Move Semantics In C++-03: rvalues sind nicht modifizierbar daher, rvalues werden einfach const T& gleichgesetzt In C++-11: neuer zusätzlicher nicht-const Referenz-Typ rvalue-referenz Typ: T && für modifizierbare Temporaries damit lassen sich sog. Move-Semantics implementieren Christof Elbrechter Praxisorientierte Einführung in C++ July 5, 2012 4 / 20
Move-Semantics mit RValue-References Move Semantics In C++-03: rvalues sind nicht modifizierbar daher, rvalues werden einfach const T& gleichgesetzt In C++-11: neuer zusätzlicher nicht-const Referenz-Typ rvalue-referenz Typ: T && für modifizierbare Temporaries damit lassen sich sog. Move-Semantics implementieren Chronisches Performance-Problem in C++-03: Temporaries, die durch implizite Umwandlung entstehen, werden tief kopiert z.b. an Funktionsinterfaces mit call by value Christof Elbrechter Praxisorientierte Einführung in C++ July 5, 2012 4 / 20
Beispiel std::vector Move Semantics struct X{ std::vector<int> v; X(const std::vector<int> &v):v(v){ ; int main(){ X myx(std::vector<int >(100)); // problem: vector wird erst angelegt // und dann noch mal kopiert gleiches problem entsteht bei return values std::vector<int> create vec(int dim) { return std::vector<int>(dim); int main(){ std::vector<int> a = create vec (100); std::vector<int> b; b = create vec (100); // hier nicht, hier gibt es die // return value optimierung // b wird erst angelegt, und // dann noch mal kopiert Christof Elbrechter Praxisorientierte Einführung in C++ July 5, 2012 5 / 20
Move-Constructor Move Semantics In C++-11, kann ein sog. move-constructor für diese Fälle definiert werden Dieser definiert, wie die Implementation eines Typs verschoben wird Im Falle des std::vector: lvalue pointer freigeben (falls nötig) rvalue pointer flach nach links kopieren rvalue pointer auf Null setzen Dann hat der lvalue die Verantwortung für die Daten Beim rvalue wird nichts aus Versehen gelöscht, da die entsprechenden Pointer auf Null gesetzt wurden Vorteil: Keine tiefe Kopie der Daten Sicher Christof Elbrechter Praxisorientierte Einführung in C++ July 5, 2012 6 / 20
Move-Constructor (2) Move Semantics Das ganze läuft unsichtbar für den Benutzer Sobald die STL angepasst ist, profitiert der Benutzer davon Der Benutzer muss nicht extra zurückgegebene Temporaries als rvalue-referenzen kennzeichnen Temporaries matchen immer zunächst rvalue-referenzen (T &&) Aus Sicherheitsgründen sind benamte Variablen niemals rvalue-referenzen auch nicht wenn man sie explizit als solche deklariert Wenn man einen rvalue benötigt, sollte std::move<t>(...) verwendet werden (siehe Beispiel) RValue References können auch nicht immer verändert werden -> Verwendung eigentlich nur für Move-Constructor vorgesehen Christof Elbrechter Praxisorientierte Einführung in C++ July 5, 2012 7 / 20
Kombination mit Variadic Templates Move Semantics In Kombination mit sog. Variadic Templates, können auch Move-Constructor basierte Factory-Funktionen erstellt werden Diese können dann alle Elemente direkt ohne jegliche Kopie an die entsprechenden Konstruktoren weiterleiten Seit C++-11 gibt es im std::vector nicht nur push_back, welches ein neues Element in den Vektor kopiert.. sondern auch emplace_back, welches ein neues Element am Ende des Vektors direkt konstruiert Vorteil: Element wird nicht erst erstellt, und dann kopiert, sondern direkt erstellt Variadisches Template template<class... Args> void std::vector<t>::emplace back(args&&... args){ / Implementation / Christof Elbrechter Praxisorientierte Einführung in C++ July 5, 2012 8 / 20
Move Semantics Beispiel std::vector<t>::emplace_back (Quelle: cppreference.com) #include <vector> #include <string> #include <iostream> struct President{ std:: string name; std:: string country; int year; ; President(std:: string && p name, std:: string && p country, int p year ): name(std::move( p name )), country(std::move( p country )), year( p year ){ std::cout << "I am being constructed.\ n"; President(President&& other) :name(std::move(other.name)), country(std::move(other.country)), year(other.year){ std::cout << "I am being moved.\ n"; President& operator=(const President& other) = default; // uses default copy, (no &&) Christof Elbrechter Praxisorientierte Einführung in C++ July 5, 2012 9 / 20
main... Move Semantics int main(){ std::vector<president> elections; std::cout << " emplace_back :\ n"; elections. emplace back(" Nelson Mandela ", " South Africa ", 1994); std::vector<president> reelections; std::cout << "\ npush_back :\ n"; reelections. push back(president(" Franklin Delano Roosevelt ", " the USA ", 1936)); std::cout << "\ ncontents :\ n"; for (President &president: elections){ // auch neu in C++11 std::cout << president.name << " was elected president of " << president.country << " in " << president.year << ".\ n"; for (President &president: reelections){ std::cout << president.name << " was re - elected president of " << president.country << " in " << president.year << ".\ n"; / Ausgabe: emplace back: I am being constructed. push back: I am being constructed. I am being moved. / Christof Elbrechter Praxisorientierte Einführung in C++ July 5, 2012 10 / 20
Generalisierte Konstante Ausdrücke constexpr keyword Hier nur ein Beispiel, ansonsten intuitiv int len() { return 100; char str[len() + 1]; // geht nicht in C++03 // in c++ 11 constexpr keyword constexpr int len() { return 100; char str[len() + 1]; // geht! Christof Elbrechter Praxisorientierte Einführung in C++ July 5, 2012 11 / 20
std::initializer_list std::initializer_list Normal für Objekte ohne Konstruktor: struct Obj{ int i; double d; ; int main(){ Obj o = { 5, 7.0 ; Obj os[] = { {0,1.0, {0,2.0; Christof Elbrechter Praxisorientierte Einführung in C++ July 5, 2012 12 / 20
Fortsetzung... std::initializer_list std::initializer_list<t> ermöglicht es, dieses Verhalten selbst zu definieren struct Vec{ Vec(std:: initializer list<float> list){... void assign(std:: initializer list<float> list){ ;... int main(){ Vec v = {1,2,3,4; v.assign ( { 1,2,3,4,5,6,7 ); z.b. in der STL nun möglich std::vector<std::string> v = {" Hello ", " ", " World "; Christof Elbrechter Praxisorientierte Einführung in C++ July 5, 2012 13 / 20
Einheitliche Initialisierung Einheitliche Initialisierung struct A{ int i; double d; std:: string s; ; struct B{ int i; double d; std:: string s; B(int i, double d):i(i),d(d),s(s){ ; int main(){ A a{ 1, 7.7, " test "; // funktioniert ohne expliziten Konstruktor.. B b{ 1, 7.7, " test "; //.. und mit auch! // und sogar: A crate a (){ return {1, 7.7, " test "; // geht auch! Christof Elbrechter Praxisorientierte Einführung in C++ July 5, 2012 14 / 20
Typinferenz Das neue auto Keyword das auto Keyword hat nun eine neue Bedeutung: auto f = boost::bind(&myfunc, 1, 1, 2, myobject); // spart einem viel Schreibarbeit auto i = 5; std::vector<std::vector<std::string> > m; //... // C++03 for(std::vector<std::vector<std::string> >::iterator it = m.begin(); it!= m.end(); ++it){... // C++11 > cool! for(auto it = m.begin(); it!= m.end(); ++it){... Christof Elbrechter Praxisorientierte Einführung in C++ July 5, 2012 15 / 20
Was, wenn man den Typ doch noch braucht? Das neue auto Keyword Dann: decltype verwenden auto i = 5; decltype(i) j = i; Christof Elbrechter Praxisorientierte Einführung in C++ July 5, 2012 16 / 20
Range-based for Range-based for Syntaktischer Zucker... int list[7] = { 1,2,3,4,5,6,7 ; int main(){ for(int &x : list){ std::cout << x << " " << std::endl; geht für fixed size Arrays icodestd::initializer_list und alles, was begin() und end() anbietet Christof Elbrechter Praxisorientierte Einführung in C++ July 5, 2012 17 / 20
Delegation der Konstruktion an andere Konstruktoren Konstruktoren nun auch möglich class Foo { int i; public: Foo(int i):i(i){ Foo() : Foo(42){ ; /// delegation and anderen Konstruktor Hier: auch mit Standardargument lösbar Generell aber notwendig, um extra Initialisierungsfunktion zu vermeiden Christof Elbrechter Praxisorientierte Einführung in C++ July 5, 2012 18 / 20
Weitere Sachen Weitere Sachen Explizites nicht-anbieten bestimmter Funktionen struct Foo{ Foo() = default; // nimmt default default Konstruktor Foo(int) {... Foo(double d) {; Foo(float) = delete; // double to float geht nicht implizit ; Christof Elbrechter Praxisorientierte Einführung in C++ July 5, 2012 19 / 20
STL Erweiterungen Support for Move-Semantics Support für UTF16 und UTF32 strings Variadic Templates (siehe emplace_back) constexpr std::thread, std::mutex, std::recursive_mutex,... template <class...types> class tuple; Hashtables: std::unordered_set std::unordered_multiset std::unordered_map std::unordered_multimap std::regex, std::regex_search, std::regex_replace std::unique_ptr, std::shared_ptr, and std::weak_ptr Zufallszahlgeneratoren std::function u.v.m... STL Erweiterungen Christof Elbrechter Praxisorientierte Einführung in C++ July 5, 2012 20 / 20