Date post: | 19-Jun-2019 |
Category: |
Documents |
Upload: | trinhkhuong |
View: | 223 times |
Download: | 0 times |
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