Semantics of C++ Seminar Wintersemester 2009/2010. RValue-Referenzen. Martin Sevenich. 6. Dezember 2009

Ähnliche Dokumente
Meeting C++ C++11 R-Value Referenzen

Praxisorientierte Einführung in C++ Lektion: "Der C++-11 Standard"

Von der Dreierregel zur Fünferregel in C++11

Einführung in die Programmierung II. 5. Zeiger

Verschlüsseln eines Bildes. Visuelle Kryptographie. Verschlüsseln eines Bildes. Verschlüsseln eines Bildes

DAP2-Programmierpraktikum Einführung in C++ (Teil 2)

Programmierkurs C/C++

Konstruktor/Destruktor

Praxisorientierte Einführung in C++ Lektion: "Smart-Pointer"

C++ Teil 5. Sven Groß. 13. Mai Sven Groß (IGPM, RWTH Aachen) C++ Teil Mai / 18

Programmieren in C++ Überladen von Methoden und Operatoren

Objektorientierte Programmierung. Kapitel 22: Aufzählungstypen (Enumeration Types)

Polymorphismus 179. Function.h. #include <string>

Objektorientierte Programmierung mit C++ SS 2007

Programmiertechnik. Teil 4. C++ Funktionen: Prototypen Overloading Parameter. C++ Funktionen: Eigenschaften

Visuelle Kryptographie. Anwendung von Zufallszahlen

Programmieren in C++ Überblick

Methoden und Wrapperklassen

C++ Templates. Wozu Templates? Definition von Templates. Gebrauch von Templates. Instanziierung und Organisation

Überblick. 5. Objekt und Klasse, Elementfunktionen

Institut für Programmierung und Reaktive Systeme. Java 6. Markus Reschke

5. Behälter und Iteratoren. Programmieren in C++ Überblick. 5.1 Einleitung. Programmieren in C++ Überblick: 5. Behälter und Iteratoren

Programmierung mit C Zeiger

Grundlagen der OO- Programmierung in C#

C++ Notnagel. Ziel, Inhalt. Programmieren in C++

Methoden. von Objekten definiert werden, Methoden,, Zugriffsmethoden und Read-Only

7. Übung Informatik II - Objektorientierte Programmierung

Einstieg in die Informatik mit Java

C++ Teil 6. Sven Groß. 27. Mai Sven Groß (IGPM, RWTH Aachen) C++ Teil Mai / 14

8. Referenzen und Zeiger

Was Mathematiker schon vor Jahrhunderten erfunden haben, gibt es jetzt endlich in ihrer Programmiersprache:

Einstieg in die Informatik mit Java

1. Übung zu "Numerik partieller Differentialgleichungen"

Einstieg in die Informatik mit Java

FH D. Objektorientierte Programmierung in Java FH D FH D. Prof. Dr. Ing. André Stuhlsatz. Referenzen. Referenzen

C++ Teil 5. Sven Groß. 8. Mai IGPM, RWTH Aachen. Sven Groß (IGPM, RWTH Aachen) C++ Teil 5 8. Mai / 16

Einstieg in die Informatik mit Java

Überblick. 6. Konstruktor und Destruktor - obligatorische Elementfunktionen einer Klasse

Programmieren - C++ Templates

Konzepte der Programmiersprachen

6 ZEIGER UND REFERENZEN - ALLGEMEINES

Praxisorientierte Einführung in C++ Lektion: "Das Schlüsselwort explicit"

Algorithmen und Datenstrukturen

Programmierkurs C/C++

Klassen. Kapitel Klassendeklaration

Einstieg in die Informatik mit Java

C Seminar. Dr.sc.nat. Michael J.M. Wagner, New Elements. Revision 89

Vererbung und Polymorphie

Java I Vorlesung 6 Referenz-Datentypen

Probeklausur: Programmierung WS04/05

Themen der Übung. Methoden und Wrapperklassen. Vorteile von Methoden. Methoden. Grundlagen

C++ Teil 9. Sven Groß. 17. Juni Sven Groß (IGPM, RWTH Aachen) C++ Teil Juni / 17

Vorkurs C++ Programmierung

Vorkurs C++ Programmierung

Objektorientierte Programmierung und Klassen

Kapitel 8. Programmierkurs. Methoden. 8.1 Methoden

Lösung der OOP-Prüfung WS12/13

3 Objektorientierte Konzepte in Java

Programmierkurs C++ Templates & STL (1/2)

Wichtige Prinzipien von C#

Algorithmen und Datenstrukturen

C-Pointer (Zeiger, Adressen) vs. C++ Referenzen

Verkettete Datenstrukturen: Listen

Pods und Objects (Klassen)

pue13 January 28, 2017

Dynamische Datentypen

Informatik II Übung 05. Benjamin Hepp 3 April 2017

Überladen von Operatoren

II. Grundlagen der Programmierung. Beispiel: Merge Sort. Beispiel: Merge Sort (Forts. ) Beispiel: Merge Sort (Forts. )

Java I Vorlesung Generics und Packages

Vorlesung Objektorientierte Programmierung Klausur

1 Polymorphie (Vielgestaltigkeit)

Programmieren - C++ Funktions-Templates

Exkurs: ANONYME KLASSEN. Techniken der Programmentwicklung Prof. Dr. Wolfgang Schramm

Praxisorientierte Einführung in C++ Lektion: "Klassen Templates"

Pass by Value Pass by Reference Defaults, Overloading, variable Parameteranzahl

Themen. Statische Methoden inline Methoden const Methoden this Zeiger Destruktor Kopierkonstruktor Überladen von Operatoren

3. Exkurs in weitere Arten der Programmierung

Wie teuer ist dynamischer Polymorphismus? 194

7.0 Arbeiten mit Objekten und Klassen

Vorlesung Programmieren

OOP und Angewandte Mathematik. Eine Einführung in die Anwendung objektorientierter Konzepte in der angewandten Mathematik

Ziel, Inhalt. Programmieren in C++ Wir lernen wie man Funktionen oder Klassen einmal schreibt, so dass sie für verschiedene Datentypen verwendbar sind

18. Vererbung und Polymorphie

Einführung zu den Klassen in C++ 107

11 Vererbung und Klassenhierarchie

Hydroinformatik I: Klassen

Funktionen Häufig müssen bestimmte Operationen in einem Programm mehrmals ausgeführt werden. Schlechte Lösung: Gute Lösung:

Modernes C++ (C++11)

Klassen als Datenstrukturen

Unterprogramme. Funktionen. Bedeutung von Funktionen in C++ Definition einer Funktion. Definition einer Prozedur

ADT: Verkettete Listen

Bei for-schleifen muss man nur immer bedenken, dass die letzte Anweisung immer erst nach der Ausführung der restlichen Anweisungen der Schleife

Zeiger in C und C++ Zeiger in Java und C/C++

Einstieg in die Informatik mit Java

Methoden. Gerd Bohlender. Einstieg in die Informatik mit Java, Vorlesung vom

Probeklausur Programmieren in C Sommersemester 2007 Dipl. Biol. Franz Schenk 12. April 2007, Uhr Bearbeitungszeit: 105 Minuten

Überblick. Überblick. Abstrakte Klassen - rein virtuelle Funktionen Beispiele

Hydroinformatik I: Klassen

Programmierkurs C++ Kapitel 6 Module Seite 1

Transkript:

Semantics of C++ Seminar Wintersemester 2009/2010 RValue-Referenzen Martin Sevenich 6. Dezember 2009 Zusammenfassung Dieser Artikel befasst sich mit den neuen RValue-Referenzen, die mit dem kommenden C++0x-Standard eingeführt werden. Betrachtet werden dabei die Unterschiede zwischen L- und RValues, sowie die Anwendungsmöglichkeiten der RValue-Referenzen, die anhand von anschaulichen Beispielen vorgestellt werden. 1

1 Einleitung Mit C++0x wird derzeit ein neuer Standard für C++ entwickelt, der einige tief greifende Erweiterungen für den Sprachkern und die Standard Template Library (STL) mit sich bringen wird. Damit soll der alte Standard von 1998 bzw. 2003 abgelöst werden. Eigentlich sollte C++0x bereits 2009 veröffentlicht werden, allerdings wird er wohl vorraussichtlich nicht vor Ende 2010 erscheinen. Unter den neuen Spracherweiterungen befinden sich unter anderem Typinferenzen und RValue-Referenzen, wobei letztere einige Probleme von C++98 mittels Move-Semantiken und Perfect-Forwarding lösen sollen.[2] Die folgende Abhandlung wird sich genauer mit ihnen befassen, indem sie zuerst eine kurze Einführung in R- und LValues gibt und schließlich die Anwendungsmöglichkeiten der neuen Referenzen vorstellt. 2 Einführung Laut dem C++-Standard ist jeder Ausdruck entweder ein LValue oder ein RValue. Um Verwirrungen zu vermeiden, muss man sich darüber klar werden, dass es nicht vom Objekt abhängt worum es sich handelt, sondern nur vom Ausdruck.[1] Ein LValue bezeichnet einen Ausdruck, der auch nach dem Anweisungsende noch existiert, der also den Strichpunkt überlebt. Zwar bedeutet LValue Left- Value, dennoch können LValues auf beiden Seiten einer Zuweisung stehen. Beispiele: 1 Object myobj ; //myobj i s t ein LValue 2 Object& myref = myobj ; // myref i s t e i n LValue 3 Object myptr ; //myptr i s t ein LValue ; 4 myobj = ( myptr + 42) ; // ( myptr + 42) i s t e i n LValue 5 myobj = (++myptr ) ; //++myptr i s t ein LValue RValues hingegen sind temporäre Objekte die auf dem Stack erzeugt werden und nach dem Ende der Anweisung verschwunden sind, also gelöscht werden. Sie sind also an keiner Stelle des Programms mehr verfügbar. Analog zu 2

LValues steht RValue für Right-Value, da sie nur auf der rechten Seite einer Zuweisung vorkommen können. Beispiele: 1 int x (123) ; // 123 i s t ein RValue 2 int z = 2 x ; // 2 x i s t ein RValue 3 z = x++; // x++ i s t ein RValue 4 s t r i n g s = Banane ; // Banane i s t ein RValue Als kleine Hilfe zur Unterscheidung von R- und LValues kann folgendes dienen:[1] Ist es möglich, die Adresse eines Ausdruckes zu bestimmen, bzw. lässt es der Compiler zu, so ist es ein LValue. Anhand der obigen Beispiele lässt sich das verdeutlichen. So sind &myobj, &*myptr und &++myptr gültige Ausdrücke, die auch problemlos akzeptiert werden. &"Banane", &(2 * x) und &123 hingegen werden vom Compiler zurückgewiesen. Da diese (temporären) Objekte nach Ende der Anweisung verschwunden sind, wäre es nicht sehr sinnvoll ihre Adresse bestimmen zu können. Es wäre sogar gefährlich dies zuzulassen, da wir keinen Einfluss darauf haben was mit diesen Objekten nach Anweisungsende passiert. So könnte ihr Speicher bereits neu belegt sein. Aus diesem Grund wird es vom C++-Compiler unterbunden. Syntax Ähnlich wie die bereits bekannten Referenzen, im Weiteren als LValue-Referenzen bezeichnet, werden RValue-Referenzen mittels zweier & deklariert und müssen auch direkt bei der Deklaration gebunden werden.[4] 1 int&& obj = (1 + 2) ; LValue-Referenzen von RValue-Referenzen und umgekehrt (Type&&&) sind nicht erlaubt. Das lässt sich zwar mit einem typedef-konstrukt umgehen, allerdings ist das Ergebnis dabei immer ein LValue.[4] 3

1 typedef int& l v a l u e ; 2 typedef int&& r v a l u e ; 3 4 void dosomething ( int& i ) {} 5 void dosomething ( l v a l u e& i ) {} // C o m p i l e r f e h l e r i s t i d e n t i s c h 6 // mit dosomething ( i n t &) 7 void dosomething ( r v a l u e& i ) {} // C o m p i l e r f e h l e r i s t i d e n t i s c h 8 // mit dosomething ( i n t &) Versucht man dosomething mit diesen drei, augenscheinlich unterschiedlichen, Signaturen zu überladen, so schlägt dies fehl. Der Compiler reduziert RValue- Referenzen auf LValue-Referenzen, sowie LValue-Referenzen auf RValue-Referenzen, zu LValue-Referenzen. Dadurch haben die drei Überladungen die identische Signatur, was den Compilierungsvorgang fehlschlagen lässt. 3 Bindungsverhalten Sowohl R- als auch LValues können konstant (const) oder veränderlich (nonconst) sein. Dabei gibt es ein bestimmtes Bindungsverhalten, wobei zu beachten ist, dass konstante Objekte niemals an veränderliche Referenzen gebunden werden können. Das soll sicherstellen, dass konstante Objekte wirklich konstant sind und nicht (gewollt oder ungewollt) verändert werden können.[1] Diese Tabelle zeigt auf welche Typen(Spalten) sich an welche Referenzen(Zeilen) binden lassen: Type& const Type& Type&& const Type&& Type& Ja Nein Nein Nein const Type& Ja Ja Ja Ja Type&& Ja Nein Ja Nein const Type&& Ja Ja Ja Ja Zu beachten ist hierbei, dass eine konstante LValue-Referenz an einen (konstanten) RValue gebunden werden kann. Da der RValue dadurch einen Namen erhält, wird er zu einem LValue. 1 const int& a = 1 2 3 ; 4

Es ist nicht sehr praktikabel eine Funktion mit allen vier Möglichkeiten zu überladen, da es ausreichend ist sich auf const Type& und Type&& zu beschränken, um alle Fälle abzudecken.[1] Welche Funktion bei welchem Argument aufgerufen wird, wird durch folgende zwei Regeln bestimmt: 1. Konstante Ausdrücke binden sich nur mit konstanten Referenzen 2. LValues binden sich bevorzugt mit LValue-Referenzen und RValues bevorzugt mit RValue-Referenzen. Beispiel: 1 void f u n c t i o n ( const s t r i n g& arg ) { 2 cout << LValue << endl ; 3 } 4 void f u n c t i o n ( s t r i n g&& arg ) { 5 cout << RValue << endl ; 6 } 7 8 int main ( ) { 9 s t r i n g a ( Test ) ; 10 f u n c t i o n ( a ) ; 11 f u n c t i o n ( s t r i n g ( Test ) ) ; 12 } Ausgabe: LValue RValue 5

4 Anwendungen 4.1 Move-Semantiken Unter move-semantiken versteht man die Möglichkeit Objekte zuweisen zu können, ohne deren Inhalt kopieren zu müssen. Anders als beim Kopieren, wird bei move keine Garantie gegeben, dass das Ursprungsobjekt unverändert bleibt. Um bei seinen Programmen eine möglichst gute Performance zu erzielen, sollten alle unnötigen Operationen vermieden werden. Doch genau das ist bei C++ schwierig und teilweise unmöglich, da die Sprache zu vielen unnötigen und zeitraubenden Kopiervorgängen zwingt. Diese Funktion soll einfach zwei Strings miteinander vertauschen:[3] 1 void swap ( s t r i n g& a, s t r i n g& b ) { 2 s t r i n g t ( a ) ; // es wird e i n e Kopie von a e r z e u g t 3 a = b ; // b wird k o p i e r t 4 b = t ; // t wird k o p i e r t 5 } Es werden also drei Kopien erzeugt, obwohl wir eigentlich keine einzige brauchen. In diesem Beispiel mag das zwar noch nicht ins Gewicht fallen, wenn jedoch statt Strings Vektoren, oder noch schlimmer Vektoren von Vektoren betrachtet werden, kann durch diese Operation viel Rechenzeit unnötig verloren gehen. Eine Möglichkeit dieses Problem zu lösen, wäre es, die Funktion swap so zu ändern, dass nur der Inhalt der beiden Objekte vertauscht wird. Allerdings wäre ein verallgemeinertes swap als Template für alle Objekte viel praktischer und eine swap-funktion für jede Klasse zu schreiben wäre viel zu viel Aufwand und würde das Problem, dass zu viel kopiert wird nur für diese eine Funktion lösen. In C++0x bieten uns RValue-Referenzen die Möglichkeit dieses Problem relativ einfach zu umgehen: Im folgenden Beispiel werden nun, statt Strings, Objekte der Klasse mystring 6

verwendet die später genauer beschrieben werden um einige Aspekte genauer betrachten zu können. 1 void swap ( mystring& a, mystring& b ) { 2 mystring t ( std : : move ( a ) ) ; 3 a = std : : move ( b ) ; 4 b = std : : move ( t ) ; 5 } Die Funktion move aus der Standard Template Library bewirkt an sich nicht viel und so ist auch ihre Definition recht kurz:[4] 1 template <Class T> 2 typename r e m o v e r e f e r e n c e <T>:: type&& 3 move (T&& a ) { 4 return a ; 5 } move akzeptiert einen L- oder RValue und gibt ihn als RValue zurück ohne ihn zu kopieren. Damit ermöglicht move dem Programmierer ein Objekt als RValue zu markieren und er kann somit kenntlich machen, dass er an dem weiteren Verbleib des Objektes nicht interessiert ist. So kann move unter Umständen ein zerstörender Aufruf sein. move alleine ermöglicht allerdings noch keine Move-Semantiken. Dafür muss noch die Klasse mystring angepasst werden. 1 class mystring { 2 public : 3 // Normaler Konstruktor 4 mystring ( const s t r i n g s ) { 5 cout << normal c o n s t r u c t o r << endl ; 6 content = new s t r i n g ( s ) ; 7 } 8 // Kopierender Konstruktor 9 mystring ( const mystring& other ) { 10 cout << copy c o n s t r u c t o r << endl ; 11 i f ( content ) content = new s t r i n g ( other. content ) ; 12 else content = NULL; 13 } 14 //Move Konstruktor 15 mystring ( mystring&& other ) { 16 cout << move c o n s t r u c t o r << endl ; 17 content = other. content ; // (1) 18 other. content = NULL; // (2) 19 } 7

20 // Kopierende Zuweisung 21 mystring& operator=(const mystring& o t h e r ) { 22 cout << copy assignment << e n d l ; 23 i f ( this!= &other ) { 24 delete content ; 25 i f ( other. content ) { 26 content = new s t r i n g ( other. content ) ; 27 } else { 28 content = NULL; 29 } 30 } 31 return this ; 32 } 33 //Move Zuweisung 34 mystring& operator=(mystring&& other ) { 35 cout << move assignment << e n d l ; 36 i f ( this!= &other ) { 37 delete content ; 38 content = other. content ; // (3) 39 other. content = NULL; // (4) 40 } 41 return this ; 42 } 43 private : 44 s t r i n g content ; 45 } ; Der normale Konstruktor, der kopierende Konstruktor und die kopierende Zuweisung funktionieren nach dem bekannten Schema. Neu sind allerdings der Move-Konstruktor und die Move-Zuweisung, die schlussendlich die Move-Semantiken ermöglichen: Der Kerngedanke dahinter ist relativ einfach:[1] Dadurch, dass ein RValue übergeben wurde, kann das Objekt manipuliert werden, ohne dass es Auswirkungen auf das restliche Programm hat, da es als temporäres Objekt nach Abschluss der Funktion gelöscht wird und nicht weiter zugreifbar ist. Diesen Umstand nutzt man um sich vom RValue Speicherplatz zu stehlen. Im Move-Konstruktor setzen wir den Pointer content auf den Pointer des anderen Objektes (1) um damit seine Daten zu übernehmen. Da nach Verlassen der Funktion das andere Objekt vernichtet wird, muss dessen Pointer auf NULL gesetzt werden (2), damit der Inhalt, den wir ja gestohlen haben, nicht auch vernichtet wird. Ähnlich funktioniert die Move-Zuweisung: Nach der Überprüfung ob es sich um dasselbe Objekt handelt, wird der Pointer des anderen Objektes übernommen 8

(3) und schließlich auf NULL gesetzt. Dieses Pattern lässt sich auf praktisch alle Klassen anwenden und sollte auch genutzt werden. Dadurch wird nicht nur der eigene Code beschleunigt,sondern auch Bibliotheksfunktionen, wie z.b. die der STL, profitieren davon. So soll im Zuge der Einführung von C++0x auch die STL entsprechend angepasst werden um durch Verwendung von RValue-Referenzen ihr Potential zu steigern.[6] 4.2 Das Forwarding-Problem Das Forwarding-Problem besteht darin, Argumente, die von einer äußeren Wrapper-Funktion erhalten wird, so an eine innere Funktion weiterzuleiten (engl. to forward), dass die äußere Funktion das identische Verhalten zeigt wie die innere. Im Folgenden wird gezeigt wo dabei Probleme auftreten und wie man sie in C++0x mit RValue-Referenzen lösen kann um ein perfectforwarding zu erhalten. Als Beispiel wird eine generische Factory-Funktion verwendet, die einen shared- Pointer für einen generischen Typ erstellt. In einer Anwendung könnte dies verwendet werden um die Objekterstellung im Code zentral zu halten.[3] 1 template<class T> 2 s h a r e d p t r <T> f a c t o r y ( ) { // Version ohne Argumente 3 return s h a r e d p t r <T>(new T( ) ) ; 4 } 5 6 7 8 template<class T, class A> 9 s h a r e d p t r <T> f a c t o r y ( const A& arg ) { // Version mit einem Argument 10 return s h a r e d p t r <T>(new T( arg ) ) ; 11 } Offensichtlich muss die Factory-Funktion dieselben Argumente akzeptieren wie die Konstruktoren der Objekte die erzeugt werden. Der Einfachheit halber beschränkt sich das Beispiel auf maximal ein Argument. Eine Verwendung könnte so aussehen: 9

1 s h a r e d p t r <C> c = f a c t o r y <C>(5) ; Allerdings gibt es einen Compilerfehler, falls der Konstruktor von C ein nichtkonstantes (non-const) Argument verlangt, da sich dieses Argument nicht an das konstante Argument der Factory-Funktion binden kann. Eine einfache Möglichkeit wäre nun die Factory-Funktion umzuschreiben: 1 template<class T, class A> 2 s h a r e d p t r <T> f a c t o r y (A& arg ) { 3 return s h a r e s p t r <T>(new T( arg ) ) ; 4 } Nun arbeitet die Factory-Funktion problemlos mit konstanten und nicht-konstanten Argumenten. 1 int i = 4 2 ; 2 const int j = 2 3 ; 3 s h a r e d p t r <C> a = f a c t o r y <C>( i ) ; // f u n k t i o n i e r t 4 s h a r e d p t r <C> b = f a c t o r y <C>( j ) ; // f u n k t i o n i e r t Allerdings ergibt sich mit dieser Lösung ein neues Problem: Anders als der Konstruktor von C akzeptiert die Factory-Funktion keine RValues mehr, da sich diese nur an eine konstante LValue-Referenz binden können. 1 C c ( 1 3 ) ; // f u n k t i o n i e r t 2 s h a r e d p t r c p = f a c t o r y <C>(13) ; // C o m p i l e r f e h l e r Dieses Problem ließe sich lösen, indem die Factory-Funktion für jede Kombination von konstanten und nicht-konstanten Argumenten überladen werden würde. In unserem Beispiel mit nur einem Argument wären zwei Überladungen notwendig, was noch akzeptabel wäre. Aber bei drei Argumenten wären es bereits acht Überladungen und bei n-argumenten 2 n Überladungen. Es ist offensichtlich, dass dies keine brauchbare Lösung ist. Auch in diesem Fall bieten uns die RValue-Referenzen eine einfache Möglichkeit dieses Forwarding-Problem zu lösen: 1 template<class T, class A> 2 s h a r e d p t r <T> f a c t o r y (A&& arg ) { 3 return s h a r e d p t r <T>(new T( std : : forward<a>(arg ) ) ) ; 4 } 10

Wie der Name der forward-funktion aus der Standard Template Library bereits vermuten lässt, wird das Argument an den Konstruktor unverändert weitergeleitet. Dabei bleibt erhalten, ob es sich um einen R- oder LValue handelt. Die Definition von std::forward:[3] 1 template<class T> 2 struct i d e n t i t y { 3 typedef T type ; 4 } 5 template<class T> 6 T&& forward (typename i d e n t i t y <T>:: type&& a ) { 7 return a ; 8 } Dank forward wird das so genannte Perfekt-Forwarding möglich, da nun für jede Anzahl an Argumenten nur eine Überladung benötigt wird. Also für n- Argumente nur eine einzige statt 2 n, was eine sehr praktikable Lösung darstellt. 5 Compiler Zwar wird es noch einige Zeit dauern bis der neue C++0x-Standard veröffentlicht wird (voraussichtlich 2010), dennoch sind RValue-Referenzen bereits im GNU g++-compiler ab Version 4.3.2 implementiert und verfügbar. Um sie nutzen zu können muss der C++0x-Modus mittels der Compiler-Option -std = c++0x aktiviert werden.[5] 6 Fazit Mit den RValue-Referenzen bietet C++0x eine praktikable Lösung für die Problematiken des Move-Semantiken und des Perfect-Forwardings. Im Falle der Move-Semantiken kann das die ohnehin schon gute Geschwindigkeit von C++- Programmen noch weiter steigern, da unnötige Kopieroperationen vermieden werden. Auch wenn ein Programmierer sie selber nicht verwendet, profitiert er durch die Verwendung in der STL doch auch davon. 11

Durch das Perfect-Forwarding wird dem Programmierer unter Umständen viel Arbeit erspart und der resultierende Code übersichtlicher und leichter wartbar. Andererseits wird C++ durch den neuen Referenztyp (type&&) und die anfangs verwirrende Unterscheidung zwischen R- und LValues noch komplexer und für Einsteiger noch schwerer zu erlernen als es ohnehin schon ist. Die Zukunft wird also zeigen müssen ob sich RValue-Referenzen durchsetzen können. 7 Quellenverzeichnis [1] Visual C++ Team Blog: RValue References: C++0x Features 3.2.2009 http://blogs.msdn.com/vcblog/archive/2009/02/03/rvalue-references-c-0x-featuresin-vc10-part-2.aspx [2] Wikipedia: C++0x - Rvalue reference and move semantics http://en.wikipedia.org/wiki/c [3] A Brief Introduction to Rvalue References 10.3.2009 http://www.artima.com/cppsource/rvalue.html [4] Rvalue - references: the basics 24.11.2008 http://codesynthesis.com/ boris/blog/2008/11/24/rvalue-reference-basics/ [5] C++0x Support in GCC 32.10.2009 http://gcc.gnu.org/projects/cxx0x.html [6]Impact of rvalue reference on the library 3.3.2005 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1771.html 12