Praxisorientierte Einführung in C++ Lektion: 'Der C++-11 ...+-11.pdf · Universität Bielefeld...

21
Universität Bielefeld Neuroinformatics Group, CITEC 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

Transcript of Praxisorientierte Einführung in C++ Lektion: 'Der C++-11 ...+-11.pdf · Universität Bielefeld...

Universität Bielefeld Neuroinformatics Group, CITEC

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

Universität Bielefeld Neuroinformatics Group, CITEC

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

Universität Bielefeld Neuroinformatics Group, CITEC Allgemeines

Allgemeines

I Eigentlich als C++-0x Standard geplantI Kam leider erst 2011I Bringt neue Features – ist aber zu 99% abwärtskompatibelI Alter Standard: C++-03 – neuer Standard: C++-11

Christof Elbrechter Praxisorientierte Einführung in C++ July 5, 2012 3 / 20

Universität Bielefeld Neuroinformatics Group, CITEC Move Semantics

Move-Semantics mit RValue-References

I In C++-03: rvalues sind nicht modifizierbarI daher, rvalues werden einfach const T& gleichgesetztI In C++-11: neuer zusätzlicher nicht-const Referenz-Typ rvalue-Referenz

Typ: T &&I für modifizierbare TemporariesI damit lassen sich sog. Move-Semantics implementieren

I Chronisches Performance-Problem in C++-03: Temporaries, die durch impliziteUmwandlung entstehen, werden tief kopiert

I z.B. an Funktionsinterfaces mit call by value

Christof Elbrechter Praxisorientierte Einführung in C++ July 5, 2012 4 / 20

Universität Bielefeld Neuroinformatics Group, CITEC Move Semantics

Move-Semantics mit RValue-References

I In C++-03: rvalues sind nicht modifizierbarI daher, rvalues werden einfach const T& gleichgesetztI In C++-11: neuer zusätzlicher nicht-const Referenz-Typ rvalue-Referenz

Typ: T &&I für modifizierbare TemporariesI damit lassen sich sog. Move-Semantics implementierenI Chronisches Performance-Problem in C++-03: Temporaries, die durch implizite

Umwandlung entstehen, werden tief kopiertI z.B. an Funktionsinterfaces mit call by value

Christof Elbrechter Praxisorientierte Einführung in C++ July 5, 2012 4 / 20

Universität Bielefeld Neuroinformatics Group, CITEC Move Semantics

Beispiel std::vector

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}

I 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); // hier nicht, hier gibt es die

// return value optimierungstd::vector<int> b;b = create vec(100); // b wird erst angelegt, und

// dann noch mal kopiert}

Christof Elbrechter Praxisorientierte Einführung in C++ July 5, 2012 5 / 20

Universität Bielefeld Neuroinformatics Group, CITEC Move Semantics

Move-Constructor

I In C++-11, kann ein sog. move-Constructor für diese Fälle definiert werdenI Dieser definiert, wie die Implementation eines Typs verschoben wirdI Im Falle des std::vector:

• lvalue pointer freigeben (falls nötig)• rvalue pointer flach nach links kopieren• rvalue pointer auf Null setzen

I Dann hat der lvalue die Verantwortung für die DatenI Beim rvalue wird nichts aus Versehen gelöscht, da die entsprechenden Pointer auf Null

gesetzt wurdenI Vorteil:

• Keine tiefe Kopie der Daten• Sicher

Christof Elbrechter Praxisorientierte Einführung in C++ July 5, 2012 6 / 20

Universität Bielefeld Neuroinformatics Group, CITEC Move Semantics

Move-Constructor (2)

I Das ganze läuft unsichtbar für den BenutzerI Sobald die STL angepasst ist, profitiert der Benutzer davonI Der Benutzer muss nicht extra zurückgegebene Temporaries als rvalue-Referenzen

kennzeichnenI Temporaries matchen immer zunächst rvalue-Referenzen (T &&)I Aus Sicherheitsgründen sind benamte Variablen niemals rvalue-Referenzen – auch nicht

wenn man sie explizit als solche deklariertI Wenn man einen rvalue benötigt, sollte std::move<T>(...) verwendet werden

(siehe Beispiel)I 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

Universität Bielefeld Neuroinformatics Group, CITEC Move Semantics

Kombination mit Variadic Templates

I In Kombination mit sog. Variadic Templates, können auch Move-Constructor basierteFactory-Funktionen erstellt werden

I Diese können dann alle Elemente direkt ohne jegliche Kopie an die entsprechendenKonstruktoren weiterleiten

I Seit C++-11 gibt es im std::vector nicht nur push_back, welches ein neues Element inden Vektor kopiert

I .. sondern auch emplace_back, welches ein neues Element am Ende des Vektors direktkonstruiert

I Vorteil: Element wird nicht erst erstellt, und dann kopiert, sondern direkt erstellt

Variadisches Templatetemplate<class... Args>void std::vector<T>::emplace back(Args&&... args){ /∗ Implementation ∗/ }

Christof Elbrechter Praxisorientierte Einführung in C++ July 5, 2012 8 / 20

Universität Bielefeld Neuroinformatics Group, CITEC 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

Universität Bielefeld Neuroinformatics Group, CITEC Move Semantics

main ...

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++11std::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

Universität Bielefeld Neuroinformatics Group, CITEC constexpr keyword

Generalisierte Konstante Ausdrücke

I Hier nur ein Beispiel, ansonsten intuitiv

int len() { return 100; }char str[len() + 1]; // geht nicht in C++03

// in c++−11 constexpr keywordconstexpr int len() { return 100; }char str[len() + 1]; // geht !

Christof Elbrechter Praxisorientierte Einführung in C++ July 5, 2012 11 / 20

Universität Bielefeld Neuroinformatics Group, CITEC std::initializer_list

std::initializer_list

I 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

Universität Bielefeld Neuroinformatics Group, CITEC std::initializer_list

Fortsetzung ...

I 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 } );

}

I 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

Universität Bielefeld Neuroinformatics Group, CITEC 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

Universität Bielefeld Neuroinformatics Group, CITEC Das neue auto Keyword

Typinferenz

I das auto Keyword hat nun eine neue Bedeutung:

auto f = boost::bind(&myFunc, 1 , 1 , 2 , myObject); // spart einem viel Schreibarbeitauto i = 5;std::vector<std::vector<std::string> > m;// ...

// C++03for(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

Universität Bielefeld Neuroinformatics Group, CITEC Das neue auto Keyword

Was, wenn man den Typ doch noch braucht?

I Dann: decltype verwenden

auto i = 5;decltype(i) j = i;

Christof Elbrechter Praxisorientierte Einführung in C++ July 5, 2012 16 / 20

Universität Bielefeld Neuroinformatics Group, CITEC Range-based for

Range-based for

I Syntaktischer Zucker ...

int list[7] = { 1,2,3,4,5,6,7 };int main(){

for(int &x : list){ std::cout << x << " " << std::endl; }}

I 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

Universität Bielefeld Neuroinformatics Group, CITEC Konstruktoren

Delegation der Konstruktion an andere Konstruktoren

I nun auch möglich

class Foo {int i;

public:Foo(int i):i(i){}Foo() : Foo(42){} /// delegation and anderen Konstruktor

};

I Hier: auch mit Standardargument lösbarI Generell aber notwendig, um extra Initialisierungsfunktion zu vermeiden

Christof Elbrechter Praxisorientierte Einführung in C++ July 5, 2012 18 / 20

Universität Bielefeld Neuroinformatics Group, CITEC Weitere Sachen

Weitere Sachen

I Explizites nicht-anbieten bestimmter Funktionen

struct Foo{Foo() = default; // nimmt default default−KonstruktorFoo(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

Universität Bielefeld Neuroinformatics Group, CITEC STL Erweiterungen

STL ErweiterungenI Support for Move-SemanticsI Support für UTF16 und UTF32 stringsI Variadic Templates (siehe emplace_back)I constexprI std::thread, std::mutex, std::recursive_mutex, ...I template <class ...Types> class tuple;I Hashtables:

• std::unordered_set• std::unordered_multiset• std::unordered_map• std::unordered_multimap

I std::regex, std::regex_search, std::regex_replaceI std::unique_ptr, std::shared_ptr, and std::weak_ptrI ZufallszahlgeneratorenI std::functionI u.v.m ...

Christof Elbrechter Praxisorientierte Einführung in C++ July 5, 2012 20 / 20