• Keine Ergebnisse gefunden

FH J¨ulich

N/A
N/A
Protected

Academic year: 2022

Aktie "FH J¨ulich"

Copied!
20
0
0

Wird geladen.... (Jetzt Volltext ansehen)

Volltext

(1)

FH J¨ ulich

Seminararbeit

C++11: Einf¨ uhrung in den neuen Standard

Author:

SamirBenmendil

Betreuer:

Prof. Dr. Christof Schelthoff Dipl. Ing. Jan-Simon Schmidt

16. Dezember 2011

(2)

Inhaltsverzeichnis

1 Einleitung 2

2 Verbesserungen am Sprachkern 2

2.1 Rvalue-Referenzen und Move-Konstruktoren . . . 2

2.2 constexpr . . . 3

2.3 Anderung der Definition von PODs . . . .¨ 5

2.4 Externe Templates . . . 5

2.5 Initialisierungslisten . . . 6

2.6 Uniforme Initialisierung . . . 6

2.7 Typinferenz . . . 7

2.8 Bereichsbasierte For-Schleifen . . . 8

2.9 Lambda-Funktionen . . . 8

2.10 Objekterstellung . . . 9

2.11 Explizite ¨Uberladung . . . 10

3 Funktionalit¨atserweiterungen 12 3.1 Variadische Templates . . . 12

3.2 defaultund delete Memberfunktionen . . . 12

3.3 Statische Zusicherungen . . . 13

3.4 Garbage Collection . . . 13

4 C++ Standardbibliothek 13 4.1 Tupel . . . 13

4.2 Hashtabellen . . . 14

4.3 Regul¨are Ausdr¨ucke . . . 14

4.4 Smart Pointers . . . 15

4.5 Zufallszahlengenerator . . . 16

4.6 Type traits f¨ur Metaprogrammierung . . . 16

Listings 18

Quellen 19

(3)

1 Einleitung

C++ist eine statisch getypte, objektorientierte Sprache, die in 1979 von Bjarne Stroustup entwickelt wurde. Sie wird oft als veraltet bezeichnet, denn sie beruht auf C, welches zwischen 1969 und 1973 von Dennis Ritchie entwickelt wurde, und garantiert volle Kompatibilit¨at mit C.

In dem neuen Standard, der hier vorgestellt wird, wurden verschiedene Anderungen und Erweiterungen implementiert, die¨ C++ wieder zu einer mo- dernen Sprache machen.

2 Verbesserungen am Sprachkern

2.1 Rvalue-Referenzen und Move-Konstruktoren

In vorherigen Versionen von C++ wurden Rvalues als unver¨anderbar ange- nommen, es war jedoch in manchen F¨allen m¨oglich und auch n¨utzlich, diese Werte zu ver¨andern.

C++11 definiert einen neuen non-const Referenztypen, welcher auf tem- por¨are Rvalues verweist, die nach der Initialisierung noch ver¨andert werden d¨urfen, um das Verschieben von Objekten zu erlauben.

Ein großes Problem bei C++03 waren die teuren und unn¨otigen deep- copies, die implizit erzeugt werden, wenn Objekte by value ¨ubergeben werden.

(4)

Listing 1: Copy- und Move-Konstruktor

c l a s s Foo {

Bar * b ; p u b l i c :

// deep - c o p y

Foo ( c o n s t Foo & o t h e r ) : b ( o t h e r . b )

{

if ( b ) b - > ref ();

}

Foo & o p e r a t o r =( c o n s t Foo & o t h e r ) { if ( o t h e r . b ) o t h e r . b - > ref ();

if ( b ) b - > u n r e f ();

b = o t h e r . b ; r e t u r n * t h i s ; }

// m o v e

Foo ( Foo && o t h e r ) : b ( o t h e r . b ) {

o t h e r . b = 0;

}

Foo & o p e r a t o r =( Foo && o t h e r ) { std :: s w a p ( b , o t h e r . b );

r e t u r n * t h i s ; }

};

In C++11 gibt es einen Move-Konstruktor, der eine Rvalue-Referenz als Parameter annimmt. Dieser gibt eine Kopie des Pointers zu dem Objekt zur¨uck und setzt den alten auf null.

2.2 constexpr

Konstante Ausdr¨ucke konnten schon seit langem in C++ optimiert werden.

Ausdr¨ucke wie z.B 3+4 konnten schon w¨ahrend des Kompilierens berechnet werden. Diese Optimierung endete aber, sobald eine Funktion im Spiel war.

Listing 2: Array-Initialisierung

int sum ( int a , int b ) { r e t u r n a + b ; } int = a r r a y [ sum (3 ,4)]; // N i c h t m ¨o g l i c h

Listing 2 ist nicht m¨oglich, da eine array-Initialisierung durch einen Kon- stanten Wert erfolgen muss; jedoch kann der Compiler die Funktion sum()

(5)

nicht als konstant betrachten, da er nicht vorhersagen kann, dass diese sich w¨ahrend der Laufzeit nicht ¨andert.

Im neuen Standard gibt es die M¨oglichkeit, Funktionen mit konstanten R¨uckgabewerten zu definieren. Dem Compiler wird durch das Schl¨usselwort constexpr angedeutet, dass der R¨uckgabewert sich w¨ahrend der Laufzeit nicht ¨andert. Auflistung 2 kann wie folgt umgeschrieben werden:

Listing 3:constexpr Array-Initialisierung

c o n s t e x p r int sum ( int a , int b ) { r e t u r n a + b ; }

int = a r r a y [ sum (3 ,4)]; // E r s t e l l t ein a r r a y der Gr ¨o ß e 7

Konstruktoren k¨onnen auch als constexpr deklariert werden, wenn sie ausschließlich aus einer konstanten Initialisierungsliste bestehen, deren Aus- dr¨ucke ebenfalls constexpr sind.

Listing 4:constexpr Konstruktor

c l a s s C o m p l e x {

d o u b l e m_a , m_b ; p u b l i c :

c o n s t e x p r C o m p l e x () : m_a {0} , m_b {0} {}

c o n s t e x p r C o m p l e x ( d o u b l e a , d o u b l e b ) : m_a { a } , m_b { b } {}

c o n s t e x p r d o u b l e a () c o n s t { r e t u r n m_a ; } c o n s t e x p r d o u b l e b () c o n s t { r e t u r n m_b ; } };

c l a s s P o l a r {

d o u b l e m_r , m _ p h i ; p u b l i c :

c o n s t e x p r P o l a r () : m_r {0} , m _ p h i {0} {}

c o n s t e x p r P o l a r ( d o u b l e r , d o u b l e phi ) : m_r { r } , m _ p h u { phi } {}

c o n s t e x p t P o l a r ( c o n s t C o m p l e x & c )

// w e n n s q r t () und a t a n 2 () e b e n f a l l s c o n s t e x p r s i n d : m_r { s q r t ( c . a () * c . a () + c . b () * c . b () ) }

, m _ p h i { a t a n 2 ( c . a () , c . b () ) } {}

};

c o n s t e x p r P o l a r p o l s [] = {

P o l a r { 0 , 0 , 100 , 100 } , P o l a r { C o m p l e x { 0 , -1 } } };

In Beispiel 4 wird polsbeim Kompilieren berechnet und der Linker legt die Variable dann im Read-only-Speicher ab.

(6)

constexpr k¨onnen die Laufzeit eines Programms deutlich verringern, erh¨ohen aber die ¨Ubersetzungszeit. Genau so wieconstin der Vorg¨angerversion, sollten constexpr ¨uberall da verwendet werden, wo es m¨oglich ist.

2.3 Anderung der Definition von PODs ¨

Ein POD struct1 ist eine Klasse, die sowohl trivial ist als auch ein Stan- dardlayout hat.

Triviale Klassen:

1. besitzen keine nicht-trivialen Konstruktoren.

2. besitzen keine nicht-trivialen Copy- und Move-Konstruktoren.

3. besitzen keine nicht-trivialen Copy- und Move-Zuweisungsoperatoren.

4. besitzen einen trivialen, nicht-virtuellen Destruktor.

Eine Klasse hat ein Standard-Layout, wenn:

1. sie weder virtuelle Funktionen noch virtuelle Basisklassen hat.

2. keine nicht-statischen Attribute eines nicht-Standardlayout-Klassentypen hat.

3. alle Attribute die gleiche Zugriffskontrolle haben (public, private, protected).

2.4 Externe Templates

Jedes Mal, wenn dem Compiler in C++03 ein Template begegnet, muss die- ses instanziiert werden. Wenn das Template in mehreren Dateien mit den gleichen Typen instanziiert wird, kann das die ¨Ubersetzungszeit drastisch erh¨ohen. Mit extern kann dem Compiler mitgeteilt werden, dass das Tem- plate in dieser ¨Ubersetzungseinheit nicht instanziiert werden soll.

// T e m p l a t e m u s s i n s t a n z i i e r t w e r d e n . t e m p l a t e c l a s s std :: vector < MyClass >;

// T e m p l a t e w i r d h i e r n i c h t i n s t a n z i i e r t . e x t e r n t e m p l a t e c l a s s std :: vector < MyClass >;

1POD steht f¨ur

plain old data“

(7)

2.5 Initialisierungslisten

C++03 hat die Initialisierungslisten von C geerbt. Man kann ein einfaches Objekt durch eine Liste von Argumenten innerhalb geschweifter Klammern initialisieren. Dies war jedoch nur f¨ur Klassen m¨oglich, die die Charakteristik eines POD-struct haben.

Es ist in C++11 m¨oglich, Initialisierungslisten f¨ur beliebige Klassen zu benutzen, indem man einen Konstruktor definiert, dessen Parametertyp eine std::initializer list ist. Es ist ebenfalls m¨oglich, diese Erweiterung bei Funktionen zu verwenden.

Listing 5:std::initializer list

c l a s s Foo {

p u b l i c :

Foo ( std :: i n i t i a l i z e r _ l i s t < int >);

v o i d f o o _ f u n c t i o n ( std : i n i t i a l i z e r _ l i s t < string >);

}

Foo foo = { 1 , 1 , 2 , 3 , 5 , 8};

Foo f o o 2 {13 , 21 , 34 , 5 5 } ;

f o o _ f u n c t i o n ({ " H a l l o " , " W e l t " , " ! " };

Einestd::initializer listkann nur statisch w¨ahrend der ¨Ubersetzung erstellt werden, deren Inhalt ist daher konstant.

2.6 Uniforme Initialisierung

C++03 hatte verschiedene Probleme mit Objektinitialisierungen. Ein Kon- struktoraufruf sieht genau so aus, wie ein Funktionsaufruf und es konnten nur Aggregate und POD-Typen mit Initialisierungslisten initialisiert werden.

C++11 erweitert die Initialisierungssyntax so, dass Variabelinitialisierun- gen uniform werden.

(8)

Listing 6: Uniforme Initialisierung

s t r u c t Foo {

int a ; d o u b l e b ; };

s t r u c t Bar {

Bar ( int a , d o u b l e b ) : m_a { a } , m_b { b } { };

Foo g e t _ f o o () { r e t u r n { a , b }; } p r i v a t e :

int m_a ; d o u b l e m_b ; };

// e i n e i n i t i a l i z e r _ l i s t w i r d h i e r i m p l i z i t b e n u t z t . Foo foo {42 , 3 . 1 4 } ;

// K o n s t r u k t o r w i r d a u f g e r u f e n . Bar bar {21 , 6 . 2 8 } ;

// Array - I n i t i a l i s i e r u n g mit new int * a = new int [3] {2 , 3 , 6};

Foo ist ein POD-struct, deshalb wird foo mit einer Initialisierungsliste erstellt. Bei bar hingegen wird der Konstruktor aufgerufen. Die Funktion get foogibt ein ObjektFoozur¨uck, ohne dass der Typ des Objektes explizit angegeben wird.

Traditionelle Konstruktorsyntax ist jedoch in manchen F¨allen noch er- forderlich. Wenn eine Klasse ebenfalls einen initializer list-Konstruktor hat, wird dieser bevorzugt, wenn die Variable mit geschweiften Klammern initialisiert wird.

2.7 Typinferenz

In vorherigen Versionen von C++musste der Typ einer Variable explizit fest- gelegt werden. Jedoch wurde das zu einem großen Problem, wenn man mit Templates gearbeitet hatte. Der R¨uckgabewert von Templates ist nicht im- mer leicht Ausdr¨uckbar wie im Listing 7 zu sehen ist. unknown type muss vom Typ T+S sein, jedoch ist dieser nicht bekannt.

(9)

Listing 7: Typinferenz

t e m p l a t e < c l a s s T , c l a s s S >

u n k n o w n _ t y p e sum ( c o n s t T & t , c o n s t S & s ) { r e t u r n s + t ; }

Der neue Standard erm¨oglicht es, mitautoden Typ einer Variablen auto- matisch zu erkennen; mit decltype kann der Typ eines Ausdrucks w¨ahrend der ¨Ubersetzung bestimmt werden.

Listing 8:auto, decltype

a u t o foo = 5; // foo w i r d zum I n t e g e r

d e c l t y p e ( foo ) bar = 6; // bar w i r d zum s e l b e n Typ wie foo

Um diese Erweiterungen bei Templates anzuwenden, muss die Syntax etwas ver¨andert werden:

Listing 9:auto, decltype

t e m p l a t e < c l a s s T , c l a s s S >

a u t o sum ( c o n s t T & t , c o n s t S & s ) - > d e c l t y p e ( s + t ) { r e t u r n s + t ; }

2.8 Bereichsbasierte For-Schleifen

C++11f¨uhrt dieforeach-Schleife in die Sprache ein. Es ist jetzt m¨oglich, eine einfache Schleife zu schreiben, die ¨uber jedes Element einer Liste iteriert.

Diese Schleife funktioniert beiC-arrays, Initialisierungslisten und jedem Typ, der begin()und end() Funktionen hat, die einen Iterator zur¨uckgeben.

Listing 10: Range-based for

int foo [5] = { 1 , 2 , 3 , 4 , 5 };

for ( int & f : foo ) { f += 10;

}

2.9 Lambda-Funktionen

Lambda-Funktionen, auch anonyme Funktionen genannt, sind eine neue Sprach- funktion in C++. Diese Funktionen werden wie folgt geschrieben:

(10)

Listing 11: Lambda-Funktionen

[] ( int a , int b ) { r e t u r n a + b ; }

[] ( int a , int b ) - > int { r e t u r n a + b ; }

Wenn der R¨uckgabetyp f¨ur jeden Aufruf der Funktion der gleiche bleibt, kann er weggelassen werden und wird mit decltype(a+b) automatisch er- kannt.

Lambda-Funktionen k¨onnen Variablen ver¨andern, die außerhalb des Funk- tionsblocks initialisiert wurden. Diese Variablen werden in den eckigen Klam- mern vor der Funktion definiert. Dies erm¨oglicht es, die Variablen entweder by value oder by reference zu ¨ubergeben. Folgende Tabelle zeigt die verschie- denen Methoden, um Variablen an die Lambda-Funktion zu ¨ubergeben.

Tabelle 1: Lambda-Funktionen

[] keine Variablen werden ¨ubergeben [a] a wird by value ¨ubergeben

[&a] a wird by reference ¨ubergeben

[=] alle Variablen werden by value ¨ubergeben [&] alle Variablen werden by reference ¨ubergeben

[a, &b] a wird by value ¨ubergeben, b wird by reference ¨ubergeben

Listing 12 zeigt ein Beispiel von Lambda-Funktionen im Einsatz. Der Maximalwert von list wird berechnet.

Listing 12: Lambda-Funktionen

std :: vector < int > l i s t ; int max = 0;

std :: f o r _ e a c h ( l i s t . b e g i n () , l i s t . end () , [& max ]( int x ) { max = x > max ? x : max ;

});

2.10 Objekterstellung

C++03 erlaubte es nicht, dass Konstruktoren andere Konstruktoren der sel- ben Klasse aufrufen. Jeder Konstruktor musste daher alle Klassenattribute selber initialisieren oder eine gemeinsame Funktion aufrufen. Ebenfalls konn- ten abgeleitete Klassen nicht mit Konstruktoren der Vaterklasse initialisiert werden, auch wenn diese gereicht h¨atten.

(11)

Im neuen Standard wurden diese Probleme gel¨ost. Auflistung 13 zeigt wie Delegation implementiert wurde.

Listing 13: Delegation

c l a s s B a s e {

int m_a ; p u b l i c :

B a s e ( int a ) : m_a { a } {}

B a s e () : B a s e { 4 2 } {}

}

c l a s s D e r i v e d : p u b l i c B a s e {

int m_b = 1;

p u b l i c :

u s i n g B a s e :: B a s e ; }

B a s e b a s e ; // b a s e hat m_a = 42

// d e r i v e d b e n u t z t den K o n s t r u k t o r den er von B a s e g e e r b t hat D e r i v e d d e r i v e d { 1 2 } ;

Der Konstruktor Base() ruft erst den Konstruktor Base(int a) mit a = 42 auf, bevor der Rumpf des Konstruktors ausgef¨uhrt wird. Die Klas- se Derived definiert keine eigene Konstruktoren, sondern benutzt die, die sie von Base geerbt hat. Es k¨onnen entweder alle Konstruktoren des Vaters benutzt werden oder keine.

Es ist mittlerweile auch m¨oglich, Attribute dort zu initialisieren, wo sie deklariert wurden:m bwird also mit1initialisiert, solange es nicht von einem Konstruktor ¨uberschrieben wird.

2.11 Explizite ¨ Uberladung

In C++03 war es m¨oglich, versehentlich eine neue virtuelle Funktion zu er- stellen, obwohl man eigentlich eine Funktion der geerbten Klasse ¨uberladen wollte. Zum Beispiel:

(12)

Listing 14: Virtuelle Funktion

c l a s s B a s e {

v i r t u a l v o i d foo ( int );

};

c l a s s D e r i v e d : B a s e {

v i r t u a l v o i d foo ( d o u b l e );

}

Die Derived::foo Funktion sollte eigentlich die Version der Basisklasse ersetzen, da jedoch die Funktionsdeklarationen nicht genau ¨ubereinstimmen, wird eine weitere virtuelle Funktion erstellt. Dieses Problem kommt h¨aufig dann vor, wenn ein Programmierer die Deklaration der Basisklassenfunktion ver¨andert.

Die Syntax von C++11 erm¨oglicht es, dieses Problem bei der Kompilati- on zu erkennen, indem override hinter der Funktionsdeklaration eingesetzt wird. Dies teilt dem Compiler mit, dass die Funktion eine andere ¨uberladen muss. Wenn der Compiler keine Funktion mit dieser Deklaration finden kann, bricht er ab und informiert den Benutzer dass ein Fehler aufgetreten ist.

Man will auch manchmal, dass eine Klasse oder Funktion nicht vererbt bzw. ¨uberladen wird. Mit final ist das im neuen Standard m¨oglich.

Listing 15: override

c l a s s F i n a l f i n a l {};

// Fehler , F i n a l d a r f n i c h t v e r e r b t w e r d e n . c l a s s D e r i v e d : F i n a l {};

c l a s s B a s e {

v i r t u a l v o i d foo ( int );

v i r t u a l v o i d bar () f i n a l ; }

c l a s s D e r i v e d : B a s e {

// Fehler , foo ( d o u b l e ) g i b t es n i c h t in B a s e v i r t u a l v o i d foo ( d o u b l e ) o v e r r i d e ;

// Fehler , bar () w u r d e in B a s e als f i n a l d e k l a r i e r t v i r t u a l v o i d bar ();

}

(13)

3 Funktionalit¨ atserweiterungen

3.1 Variadische Templates

Ab C++11 k¨onnen Klassen- und Funktions-Templates eine beliebige Anzahl an Parametern annehmen.

3.2 default und delete Memberfunktionen

DerC++Compiler erstellt f¨ur jede Klasse ein Default-Konstruktor, ein Copy- Konstruktor, ein Zuweisungsoperator (operator=) und einen Destruktor, wenn diese nicht deklariert wurden. C++11 erlaubt es explizit festzulegen, dass die Default-Implementationen benutzt werden. Da der Compiler keinen Default-Konstruktor erstellt, wenn irgend ein Konstruktor deklariert wurde ist es zum Vorteil dass C++11 es erlaubt die Default-Implementationen des Konstruktors zu deklarieren.

Listing 16: default

s t r u c t Foo {

// Default - K o n s t r u k t o r w i r d e x p l i z i t d e k l a r i e r t . Foo () = d e f a u l t ;

Foo ( int );

};

Es ist jetzt auch erlaubt, Konstruktoren oder Funktionen zu l¨oschen, wenn diese nicht benutzt werden sollen. Zum Vorteil wird diese Erweiterung bei Klassen, die nicht kopierbar sind, wie auch f¨ur das Singleton-Pattern. In Listing 17 werden der Zuweisungsoperator und der Copy-Konstruktor de- aktiviert. Die Klasse Bar ist hiermit nicht kopierbar. Die Funktion f(int) wird ebenfalls deaktiviert, f() kann also nicht mit einem int aufgerufen werden. Implizites casting in ein double wird f¨ur diese Funktion nicht mehr unterst¨utzt.

(14)

Listing 17: delete

s t r u c t Bar {

Bar & o p e r a t o r =( c o n s t Bar &) = d e l e t e ; Bar ( c o n s t Bar &) = d e l e t e ;

Bar () = d e f a u l t ; int f ( int ) = d e l e t e ; int f ( d o u b l e );

};

3.3 Statische Zusicherungen

Assertions wurden in C++03 entweder zur Laufzeit mit assert() oder vom Pr¨aprozessor mit #error getestet. Diese Zusicherungen sind aber nicht f¨ur Templateparameter geeignet, da diese vor dem Kompilieren noch nicht zur Verf¨ugung stehen. Die neuen static assert-Makros testen w¨ahrend dem Ubersetzen.¨

Listing 18: static assert

s t a t i c _ a s s e r t ( e x p r e s s i o n , f e h l e r _ m e l d u n g );

3.4 Garbage Collection

Der neue Standard erlaubt Implementationen mit automatischer Speicher- bereinigung. Es ist also den Entwicklern von Compilern freigestellt, ob sie einen Garbage-Collector unterst¨utzen oder nicht.

4 C++ Standardbibliothek

4.1 Tupel

Dank variadischer Templates ist es m¨oglich, Tupel in C++zu definieren.

Listing 19: tuple

t y p e d e f std :: tuple < std :: string , int > t u p l e _ t y p e ; t u p l e _ t y p e foo ( " M e a n i n g of L i f e " , 4 2 ) ;

int n = std :: get <1 >( foo ); // n = 42 std :: get <0 >( foo ) = " m o l y b d e n u m " ;

(15)

4.2 Hashtabellen

Mit Hashtabellen wurde ein lang erwartetes Feature in die Standard Templa- te Library implementiert. Kollisionen werden in dieser Version nur mit Ver- kettung gel¨ost. Um Kompatibilit¨at mit nicht-Standardbibliotheken zu ver- meiden, wurde unordered statt hash verwendet. Es gibt vier verschiedene Sorten von Hashtabellen:

1. std::unordered set hat keine Duplikate.

2. std::unordered multiset erlaubt Duplikate.

3. std::unordered map 4. std::unordered multimap

4.3 Regul¨ are Ausdr¨ ucke

Regul¨are Ausdr¨ucke werden ab sofort direkt von der Standard Bibliothek unterst¨utzt. Dazu wird erstmals ein Objekt des Typs std::regex erstellt, mit dem man innerhalb von strings und C-arrays suchen und ersetzen kann. Das Ergebnis der Suche wird in einemstd::smatchoderstd::cmatch gespeichert, abh¨angend davon, ob man ein string oder ein const char * haben will.

Listing 20: regex

// R e g e x

c o n s t c h a r * r e g _ e s p = " [ ,.\\ t \\ n ;:] " ; std :: r e g e x rgx ( r e g _ e s p );

std :: c m a t c h m a t c h ;

c o n s t c h a r * t a r g e t = " U n s e e n U n i v e r s i t y - Ankh - M o r p o r k " ;

// S u c h t a l l e C h a r a k t e r , die d u r c h ’ r e s p _ e s p ’ g e t r e n n t w u r d e n . if ( std :: r e g e x _ s e a r c h ( target , match , rgx ) ) {

// W e n n w e l c h e g e f u n d e n w o r d e n . c o n s t s i z e _ t n = m a t c h . s i z e ();

for ( s i z e _ t a = 0; a < n ; a ++ ) {

std :: s t r i n g str ( m a t c h [ a ]. first , m a t c h [ a ]. s e c o n d );

std :: c o u t < < str < < " \ n " ; }

}

(16)

4.4 Smart Pointers

C++11 f¨uhrt drei verschiedene Smart Pointer ein.

1. unique ptr k¨onnen nicht einer anderen Variablen zugewiesen werden.

Deren Copy-Konstruktor und Zuweisungsoperator wurden explizit de- aktiviert. Es ist jedoch m¨oglich, diese Zeiger mittels std::move()auf eine andere Variable zu verschieben.

Listing 21: unique ptr

std :: u n i q u e _ p t r < int > foo ( new int ( 4 2 ) ) ;

std :: u n i q u e _ p t r < int > bar = foo ; // ¨U b e r s e t z u n g s f e h l e r // f o o 2 z e i g t auf den S p e i c h e r von foo , foo w i r d ung ¨u l t i g . std :: u n i q u e _ p t r < int > f o o 2 = std :: m o v e ( foo );

f o o 2 . r e s e t (); // S p e i c h e r w i r d b e f r e i t .

2. shared ptr werden zur Referenzz¨ahlung benutzt. Jede Kopie eines shared ptrbesitzt den gleichen Pointer. Dieser Verweis wird nur dann gel¨oscht, wenn alle Instanzen des shared ptr zerst¨ort wurden.

Listing 22: shared ptr

std :: s h a r e d _ p t r < int > foo ( new int ( 4 2 ) ) ; std :: s h a r e d _ p t r < int > f o o 2 ( new int ( 4 2 ) ) ; int cnt = foo . u s e _ c o u n t (); // cnt = 2

d e l e t e f o o 2 ; // S p e i c h e r ist n o c h v o r h a n d e n // f o o 2 ist ung ¨u l t i g

d e l e t e foo ; // O b j e k t w i r d z e r s t ¨o rt

3. weak ptr vermeiden zyklische Verweise, indem sie die gleichen Eigen- schaften besitzen, wie shared ptr, aber ohne den Referenzz¨ahler zu erh¨ohen. Ein Objekt wird gel¨oscht, wenn es nur durch weak ptr refe- renziert wird.

Listing 23: weak ptr

std :: s h a r e d _ p t r < int > foo ( new int ( 4 2 ) ) ; std :: w e a k _ p t r < int > bar ( new int ( 4 2 ) ) ;

d e l e t e foo ; // S p e i c h e r w i r d f r e i g e g e b e n

(17)

4.5 Zufallszahlengenerator

Die C Standardbibliothek bietet die M¨oglichkeit, Pseudozufallszahlen mit rand zu generieren, jedoch wurde dem Compiler ¨uberlassen, wie diese Zah- len zu berechnen sind. C++hat diese Funktionalit¨at vonCgeerbt,C++11wird neue Methoden zur Generierung von Pseudozufallszahlen zur Verf¨ugung stel- len.

Diese Funktionalit¨at wird in zwei geteilt: es gibt auf der einen Seite ei- ne Generatorengine, die den Zustand des Zahlengenerators beinhaltet und Pseudozufallszahlen ausgibt, auf der anderen Seite wird eine mathematische Distribution festgelegt, die den Wertebereich der Zufallszahlen bestimmt.

Folgende Distributionen werden vonC++11 unterst¨utzt:

1. uniform int distribution 2. bernoulli distribution 3. geometric distribution 4. poisson distribution 5. binomial distribution 6. uniform real distribution 7. exponential distribution 8. normal distribution 9. gamma distribution

4.6 Type traits f¨ ur Metaprogrammierung

Metaprogrammierung wird inC++h¨aufig benutzt. Es wird dabei ein Template erstellt, das Werte w¨ahrend der ¨Ubersetzung und nicht w¨ahrend der Laufzeit berechnet. Dadurch wird das Programm um einiges beschleunigt, was aber mit einem Zeitverlust w¨ahrend des Kompilierens erkauft wird.

Type Traits k¨onnen Eigenschaften von Objekten erkennen. Es ist dann m¨oglich, mit dieser Information auf verschiedene Typen anders zu reagieren.

Listing 24 zeigt, wie man zwischen zwei Funktionen, basierend auf dem Parametertyp, w¨ahlt.

(18)

Listing 24: Type Traits

// E r s t e F u n k t i o n .

t e m p l a t e < b o o l B > s t r u c t A l g o r i t h m {

t e m p l a t e < c l a s s T1 , c l a s s T2 > s t a t i c int foo ( T1 & , T2 &) { /* ... */ }

};

// Z w e i t e F u n k t i o n .

t e m p l a t e < > s t r u c t A l g o r i t h m < true > {

t e m p l a t e < c l a s s T1 , c l a s s T2 > s t a t i c int foo ( T1 , T2 ) { /* ... */ }

};

// W e n n ’ f o o b a r ’ i n s t a n z i i e r t wird , w i r d a u t o m a t i s c h die // r i c h t i g e F u n k t i o n a u f g e r u f e n

t e m p l a t e < c l a s s T1 , c l a s s T2 >

int f o o b a r ( T1 A , T2 B ) {

// B e n u t z t die 2. F u n k t i o n nur w e n n ’ T1 ’ und ’ T2 ’ b e i d e // I n t e g e r sind , a n s o n s t e n w i r d die 1. F u n k t i o n a u s g e f ¨u hrt . r e t u r n A l g o r i t h m < std :: i s _ i n t e g r a l < T1 >:: v a l u e

&& std :: i s _ i n t e g r a l < T2 >:: value >:: foo ( A , B );

};

(19)

Listings

1 Copy- und Move-Konstruktor . . . 3

2 Array-Initialisierung . . . 3

3 constexpr Array-Initialisierung . . . 4

4 constexpr Konstruktor . . . 4

5 std::initializer list . . . 6

6 Uniforme Initialisierung . . . 7

7 Typinferenz . . . 8

8 auto, decltype . . . 8

9 auto, decltype . . . 8

10 Range-based for . . . 8

11 Lambda-Funktionen . . . 9

12 Lambda-Funktionen . . . 9

13 Delegation . . . 10

14 Virtuelle Funktion . . . 11

15 override . . . 11

16 default . . . 12

17 delete . . . 13

18 static assert . . . 13

19 tuple . . . 13

20 regex . . . 14

21 unique ptr . . . 15

22 shared ptr . . . 15

23 weak ptr. . . 15

24 Type Traits . . . 17

(20)

Literatur

[1] Bjarne Stroustrup, The C++ Programming Language. Addison Wesley, Massachusetts, Special Ed., 2010.

[2] [ISO N3242]Working Draft, Standard for Programming Language C++, 2011-02-28

[3] http://en.wikipedia.org/wiki/C++11

[4] http://www.heise.de/developer/artikel/C-11-auch-ein-Stimmungsbild-1345406.html

Abbildung

Tabelle 1: Lambda-Funktionen

Referenzen

ÄHNLICHE DOKUMENTE

Wenn wir also einen Konstruktor f¨ ur Student schreiben, sollten wir sicherstellen, daß mit diesem auch ein g¨ ultiges Objekt der Klasse Person erzeugt wird. Hierzu kann man

In Java: default constructor ist der vom Compiler erzeugte Konstruktor ohne Parameter. • Er tr¨ agt (wie in Java) den Namen der Klasse und hat keine R¨ uckgabe class

• ∆ Mini: Annot erweitert (durch Seiteneffekt) die globale Umgebung um neue Klassen erweitert, sobald diese referenziert werden. • F¨ ur die Rekursion scheinen die Klassen schon

• ∆ Mini: Annot erweitert (durch Seiteneffekt) die globale Umgebung um neue Klassen erweitert, sobald diese referenziert werden. • F¨ ur die Rekursion scheinen die Klassen schon

Sprachen wie While sind damit nicht direkt auf einem solchen Rechner ausf¨ uhrbar, sondern m¨ ussen ¨ ubersetzt werden.. Die Regeln der Big-Step-Semantik (und auch

Dabei wird aber das auszuf¨ uhrende Programm selbst nicht in eine f¨ ur den Rechner geeignetere Darstellung ¨ ubersetzt.. Direkter geht es, wenn man einen solchen Rechner und

Employing code annota- tions and an additional compiler pass, we are able to track and replace low-level load instructions that refer to operator parameters which remain constant

Schreiben Sie einen Konstruktor, der zwei Parameter erhält (geldbestand, passwort) und mit diesen Werten die