Einsatzgebiet von Const-RValue-Referenzen
-
Hallo,
Eine kurze Frage zu RValue-Referenzen in C++0x: Welchen Sinn haben RValue-Referenzen auf
const-qualifizierte Typen, alsoconst T&&? Soweit ich das sehe, kann manconst-RValues an sie binden, was beiT&&nicht geht.Das wirft natürlich die Frage auf, wann man überhaupt
const-qualifizierte RValues benötigt. Mir scheint, sie sind oft eine unnötige Einschränkung. Ich kann mir vorstellen, dass konstante RValues vor allem aus merkwürdigen Designs wie dem folgenden resultieren.const Matrix operator+ (const Matrix& lhs, const Matrix& rhs); // const-Rückgabe verhindert den immer wieder vorkommenden Fehler // (a + b) = c; und macht daher alle Programme sicherer!Denn bei RValues stört es ja prinzipiell niemanden, ob sie geändert werden (darin besteht schliesslich ein grosses Optimierungspotenzial durch Move-Semantik). Mit
constkann man das temporäre Objekt hingegen nicht ändern und so kein Resource-Stealing betreiben.Oder geht es mehr um lokale Sicherheit, also ähnlich wie hier?
void Function(const int i) { // Ich kann i nicht aus Versehen ändern! }Dann verstehe ich aber nicht ganz, warum man nicht gleich
const T&stattconst T&&nimmt. Möglicherweise, weil der Compiler beim Binden eines temporären Objekts anconst T&prinzipiell eine Kopie durchführen darf? Doch was für ein Compiler unterstützt RValue-Referenzen, optimiert aber so eine Kopie nicht weg?Das Letzte, was ich mir vorstellen könnte, wäre Generizität. Also dass folgendes Konstrukt möglich ist, wenn
Uconst-qualifiziert ist.typedef U&& rvalue_reference;Dagegen ist eigentlich nichts einzuwenden. Aber gibt es einen Fall, in dem es vernünftig ist, explizit den Typen
const T&&(fürTirgendwas eingesetzt) zu benutzen?Edit: Threadtitel
-
Nexus schrieb:
Eine kurze Frage zu RValue-Referenzen in C++0x: Welchen Sinn haben RValue-Referenzen auf
const-qualifizierte Typen, alsoconst T&&? Soweit ich das sehe, kann manconst-RValues an sie binden, was beiT&&nicht geht.Wenn T deduziert wird, schon. Dann wird eben T = const Soundso.

Nexus schrieb:
Das wirft natürlich die Frage auf, wann man überhaupt
const-qualifizierte RValues benötigt.Warum soll man sie denn künstlich verbieten? Das erhöht doch nur die Zahl der Irregularitäten in C++.
Nexus schrieb:
Mir scheint, sie sind oft eine unnötige Einschränkung. Ich kann mir vorstellen, dass konstante RValues vor allem aus merkwürdigen Designs wie dem folgenden resultieren.
const Matrix operator+ (const Matrix& lhs, const Matrix& rhs); // const-Rückgabe verhindert den immer wieder vorkommenden Fehler // (a + b) = c; und macht daher alle Programme sicherer!*seufz*
Das soll ein immer wieder vorkommender Fehler sein? Das halte ich für ein Gerücht. Ich weiß, dass das einer von Scott Meyers' Tipps ist, aber wenn Du ihn heute fragen würdest, würde er sagen, dass das Zurückgeben von konstanten Objekten eine schlechte Idee sei, weil es "Move-Semantics" aushebelt. Das ist sogar belegt (findest Du in einer der C++ Newsgroups. Bin aber zu faul, das rauszusuchen).Nexus schrieb:
Denn bei RValues stört es ja prinzipiell niemanden, ob sie geändert werden (darin besteht schliesslich ein grosses Optimierungspotenzial durch Move-Semantik). Mit
constkann man das temporäre Objekt hingegen nicht ändern und so kein Resource-Stealing betreiben.Genau.
Nexus schrieb:
Oder geht es mehr um lokale Sicherheit, also ähnlich wie hier?
void Function(const int i) { // Ich kann i nicht aus Versehen ändern! }Dann verstehe ich aber nicht ganz, warum man nicht gleich
const T&stattconst T&&nimmt.Ich verstehe dieses Beispiel mit Deiner Bemerkung nicht. Ist da vielleicht ein Tippfehler dabei? Fehlt da ein && im Code?
Nexus schrieb:
Möglicherweise, weil der Compiler beim Binden eines temporären Objekts an
const T&prinzipiell eine Kopie durchführen darf? Doch was für ein Compiler unterstützt RValue-Referenzen, optimiert aber so eine Kopie nicht weg?Zusammenhang?
Nexus schrieb:
Das Letzte, was ich mir vorstellen könnte, wäre Generizität. Also dass folgendes Konstrukt möglich ist, wenn
Uconst-qualifiziert ist.typedef U&& rvalue_reference;Dagegen ist eigentlich nichts einzuwenden. Aber gibt es einen Fall, in dem es vernünftig ist, explizit den Typen
const T&&(fürTirgendwas eingesetzt) zu benutzen?Ich verstehe Dich hier leider nicht.
Rvalue-Referenzen auf const können zB in folgenden Kontexten vorkommen:
reference_wrapper<const string> hat zwei Konstruktoren:
...::reference_wrapper(const string &);
...::reference_wrapper(const string &&) = delete;
(kann man also nicht mit Rvalue-Ausdrücken initialisieren, ob const oder nicht)Bei Template-Argument-Deduktion:
template<class T> void sink(T&&) { cout << "Argument war ein "; if (is_lvalue_reference<T>::value) { cout << "Lvalue"; } else { cout << "Rvalue"; } cout << "-Ausdruck\n"; } const string source(); void foo() { sink(source()); // T = string const, T&& = string const&& const string s = source(); std::ref(s); // OK std::ref(source()); // Fehler, (c)ref/reference_wrapper mag keine Rvalues }Ich verstehe jetzt aber Dein Problem nicht ganz. const/non-const und &-vs-&& sind größtenteils twei orthogonale Konzepte. Es gibt lediglich die Ausnahme, dass Du eine "lvalue-Referenz auf const" auch mit einem temporären Objekt initialisieren kannst. Das war's.
Gruß,
kk
-
Vielen Dank für die Antwort. Ich habe übrigens die von dir empfohlene Artikel-Reihe auf C++Next angeschaut, danke nochmals dafür!
krümelkacker schrieb:
*seufz*
Das soll ein immer wieder vorkommender Fehler sein? Das halte ich für ein Gerücht.Hehe, das war ironisch gemeint. Ich bin völlig deiner Meinung.

krümelkacker schrieb:
Ich verstehe dieses Beispiel mit Deiner Bemerkung nicht. Ist da vielleicht ein Tippfehler dabei? Fehlt da ein && im Code?
Nein, das sollte mehr eine Analogie sein. Mit "lokaler Sicherheit" meinte ich, dass Code innerhalb von
Functionnicht aus Versehen ein Objekt ändert, das nicht dazu vorgesehen ist. Ich bin kein Vertreter von Top-Level-constin Parametern. Bei RValue-Referenzen sind es zwar keine Top-Level-CVs mehr, aber der Gedanke ("ich muss die Kopie nicht ändern, also mach ich sie konstant") könnte der gleiche bleiben. Ich habe mir halt ein paar Anwendungsfälle ausgedacht und überlegt, dass jemand Const-RValue-Referenzen zu diesem Zweck einsetzen könnte (was aber nicht allzu viel Sinn zu machen scheint).krümelkacker schrieb:
Zusammenhang?
Wenn man das eben Beschriebene erreichen möchte, könnte man auch
const T&stattconst T&&nehmen und hätte gleichzeitig auch LValues eingeschlossen. Als Nachteil vonconst T&in diesem Zusammenhang ist mir nur die potenzielle unnötige Kopie in den Sinn gekommen.krümelkacker schrieb:
Ich verstehe jetzt aber Dein Problem nicht ganz. const/non-const und &-vs-&& sind größtenteils twei orthogonale Konzepte.
Ich beschäftige mich erst seit Kurzem mit C++0x-Konzepten und kenne daher noch kaum gebräuchliche Idiome oder Best Practices. Mir geht es nicht darum, RValue-Referenzen auf
constganz zu verbieten, schliesslich habe ich am Schluss auch Anwendungsfälle gesehen. Ich frage mich eher, ob es viele Kontexte gibt, in denen man sie direkt (nicht deduziert oder in Templates, sondern explizit) hinschreibt. Also wann man sowas programmiert:class MyClass { ... }; void Function(const MyClass&& ref);Bei "normalen" RValue-Referenzen (
MyClass&& ref) kommt ja sowas ab und zu vor. Ich erkundige mich mehr nach dem Einsatzgebiet als nach dem Sinn vonconst MyClass&&(der Threadtitel ist etwas ungünstig, ich ändere ihn).
-
Hat jemand eine Idee für eine direkte Anwendung von
const T&&? Seid kreativ
-
Nexus schrieb:
Hat jemand eine Idee für eine direkte Anwendung von
const T&&? Seid kreativ
siehe std::ref und std::cref zum Beispiel
template<class T> reference_wrapper<const T> cref(T const&); template<class T> void cref(T const&&) = delete;--> cref lässt sich nur mit Lvalues aufrufen -- aus Sicherheitsgründen.
-
Ah, in deinem oberen Beispiel war das schon explizit und nicht deduziert, okay. Danke!
Vielleicht frag ich in 1-2 Jahren nochmals, wenn C++0x fertig ist und vielleicht auch von ein bisschen mehr Leuten verwendet wird.
