Elle déclare une référence rvalue (proposition de normes doc).
Voici une introduction à la rvalue references: http://www.artima.com/cppsource/rvalue.html.
Voici un fantastique regard en profondeur sur les références rvalue par l'un de Microsoft de la bibliothèque standard, les développeurs: http://blogs.msdn.com/b/vcblog/archive/2009/02/03/rvalue-references-c-0x-features-in-vc10-part-2.aspx.
La plus grande différence entre un C++03 référence (maintenant appelé une lvalue de référence en C++0x), c'est qu'il peut se lier à une rvalue temporaire sans avoir à être const. Ainsi, cette syntaxe est maintenant légal:
T&& r = T();
références rvalue principalement les suivantes:
La sémantique de déplacement. Un constructeur de déplacement et d'assignation de déplacement de l'opérateur peut désormais être défini qui prend une référence rvalue au lieu de l'habituel const-lvalue de référence. Un déplacement des fonctions comme une copie, sauf qu'il n'est pas obligé de garder la source inchangée; en fait, il modifie la source de sorte qu'il ne possède plus le déplacé ressources. C'est excellent pour éliminer les copies superflues, en particulier dans les implémentations de la bibliothèque standard.
Par exemple, un constructeur de copie pourrait ressembler à ceci:
foo(foo const& other)
{
this->length = other.length;
this->ptr = new int[other.length];
copy(other.ptr, other.ptr + other.length, this->ptr);
}
Si ce constructeur a été adoptée temporaire, la copie serait inutile parce que nous savons temporaire sera détruit; pourquoi ne pas utiliser les ressources temporaires déjà alloué? En C++03, il n'y a aucun moyen d'empêcher la copie que nous ne pouvons pas déterminer nous avons passé un temporaire. Dans C++0x, on peut surcharger un constructeur de déplacement:
foo(foo&& other)
{
this->length = other.length;
this->ptr = other.ptr;
other.length = 0;
other.ptr = nullptr;
}
Avis de la grande différence ici: le constructeur de déplacement modifie en fait son argument. Cela permettrait effectivement de "déplacer" le temporaire de l'objet en cours de construction, ce qui élimine la copie superflue.
Le constructeur de déplacement serait utilisé pour les temporaires et pour les non-const lvalue références qui sont explicitement convertis aux références rvalue à l'aide de l' std::move
de la fonction (il vient effectue la conversion). Le code suivant à la fois invoquer le constructeur de déplacement pour f1 et f2:
foo f1((foo())); // Move a temporary into f1; temporary becomes "empty"
foo f2 = std::move(f1); // Move f1 into f2; f1 is now "empty"
Le transfert parfait. références rvalue nous permettre de bien des arguments pour templated fonctions. Prenez l'exemple de cette usine de la fonction:
template <typename T, typename A1>
std::unique_ptr<T> factory(A1& a1)
{
return std::unique_ptr<T>(new T(a1));
}
Si nous avons appelé usine<toto>(5), l'argument va être déduites à int&
, qui ne pourront pas se lier à un littéral 5, même si foo constructeur prend un int. Eh bien, on pourrait plutôt utiliser A1 const&
, mais que faire si foo prend l'argument du constructeur par des non-const de référence? Pour faire un véritable générique de l'usine de fonction, nous aurions à la surcharge de l'usine sur A1&
et A1 const&
. Qui pourrait être bien si l'usine prend 1 type de paramètre, mais chaque type de paramètre permettrait de multiplier la surcharge nécessaire de définir par 2. C'est très rapidement désuète.
références rvalue résoudre ce problème en permettant à la bibliothèque standard de définir un std::forward
fonction qui peut correctement le lvalue/références rvalue. Pour plus d'informations sur comment std::forward
, voir cette excellente réponse.
Cela nous permet de définir l'usine de la fonction comme ceci:
template <typename T, typename A1>
std::unique_ptr<T> factory(A1&& a1)
{
return std::unique_ptr<T>(new T(std::forward<A1>(a1)));
}
Maintenant l'argument de la rvalue/lvalue-ness est préservée lorsqu'il est passé à T du constructeur. Cela signifie que si l'usine est appelée avec une valeur r, T du constructeur est appelé avec une rvalue. Si l'usine est appelée avec une lvalue, des T-constructeur est appelé avec une lvalue. L'amélioration de la fonction de fabrication des œuvres, car d'une règle spéciale:
Lorsque le paramètre de la fonction est du type de
la forme de la T&& où T est un modèle
paramètre, et l'argument de la fonction
est une lvalue de type A, de type A et est
utilisé pour l'argument de modèle déduction
Ainsi, nous pouvons utiliser l'usine comme suit:
auto p1 = factory<foo>(foo()); // calls foo(foo&&)
auto p2 = factory<foo>(*p1); // calls foo(foo const&)
Important référence rvalue propriétés:
- Pour la résolution de surcharge, lvalues préfèrent la liaison lvalue des références et des rvalues préfèrent la liaison références rvalue. Donc pourquoi temporaires préfèrent invoquer un constructeur de déplacement / opérateur d'assignation de déplacement de plus d'un constructeur de copie / opérateur d'affectation.
-
références rvalue sera implicitement se lier à des rvalues et temporaires qui sont le résultat d'une conversion implicite. c'est à dire
float f = 0f; int&& i = f;
est bien formée, car le flotteur est implicitement converti en int; la référence à une temporaire qui est le résultat de la conversion.
-
Nommé références rvalue sont lvalues. Sans nom rvalue references sont rvalues. C'est important de comprendre pourquoi l'
std::move
appel est nécessaire: foo&& r = foo(); foo f = std::move(r);