2009-05-09 11 views
20

L'une des nouvelles fonctionnalités du nouveau standard C++, C++ 0x, est "les références rvalue". Une référence rvalue est similaire à une lvalue référence (normal), sauf qu'il peut être lié à une valeur temporaire (normalement, un temporaire ne peut être lié à une référence const):Pourquoi la référence C++ 0x rvalue n'est-elle pas la valeur par défaut?

void FunctionWithLValueRef(int& a) {...} 
void FunctionWithRValueRef(int&& a) {...} 

int main() { 
    FunctionWithLValueRef(5); // error, 5 is a temporary 
    FunctionWithRValueRef(5); // okay 
} 

Alors, pourquoi ont-ils Inventer un tout nouveau type, au lieu de simplement supprimer les restrictions sur les références normales pour leur permettre d'être lié à des temporaires?

+3

Je me demande pourquoi cela a eu 3 votes mais 7 favoris. Je ne pense pas avoir jamais favorisé une question sans l'avoir votée (à moins que je ne sois exclu ou que je l'ai verrouillé). – Zifre

+3

Je me demande pourquoi quelqu'un pense d'une certaine façon et ensuite il s'attend à ce que tous les autres fassent exactement ce qu'il fait. – user534498

+1

Je me demande pourquoi "être gentil et donner un upvote" est une attente déraisonnable. –

Répondre

43

Ce serait inutile. Vous changeriez la chose dans la fonction, et le changement serait perdu immédiatement parce que la chose était en fait temporaire.

La raison du nouveau type découle du besoin de pouvoir décider ce qui est réellement une valeur et quoi d'autre. Seulement alors vous pouvez les utiliser pour les choses cool qu'ils sont utilisés.

string toupper(string && s) { // for nonconst rvalues 
    for(char &c : s) make_uppercase(c); 
    return move(s); // move s into a returned string object 
} 

string toupper(string const& s) { // for the rest 
    // calls the rvalue reference version, by passing 
    // an rvalue copy. 
    return toupper(string(s)); 
} 

Maintenant, si vous avez des rvalue et passez à toUpper, le rvalue peut directement être modifiée, parce que nous savons que le temporaire est une chose à jeter de toute façon, donc on peut aswell changer juste et n » t besoin de le copier. En outre, la même observation est utilisée pour la chose appelée move-constructors et move-assignment. Le côté droit n'est pas copié, mais ses objets sont simplement volés et déplacés vers . Si vous deviez dire que les valeurs peuvent se lier à des références de lvalue non const, vous n'auriez aucun moyen de savoir si cela fait référence à une lvalue (objet nommé) ou à une valeur rvalue (temporaire) à la fin.


Il est probablement plus peu de savoir, mais utile de toute façon, vous pouvez mettre lvalue ou rvalue ref-qualificatifs sur une fonction membre. Voici un exemple qui étend naturellement la sémantique existante des références rvalue au paramètre d'objet implicite:

struct string { 
    string& operator=(string const& other) & { /* ... */ } 
}; 

Maintenant, vous ne pouvez pas dire plus

string() = "hello"; 

Ce qui est source de confusion et n'est pas vraiment faire sentir la plupart du temps. Ce que dit le & ci-dessus, c'est que l'opérateur d'affectation ne peut être invoqué que sur lvalues. La même chose peut être faite pour les valeurs, en mettant &&.

+1

+1 Wow merci pour la dernière partie sur l'appel lvalues ​​/ rvalues ​​only member!J'ai beaucoup lu sur le C++ 0x mais je n'ai rien vu à ce sujet (je suppose que c'est dans le dernier brouillon mais je n'ai pas tout lu). Pouvez-vous me montrer une documentation sur cette fonctionnalité? – Klaim

+0

Voici un bel aperçu: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1821.htm. Dans le document de travail, voir 8.3.5, 9.3.1 et 13.3.1. –

+0

Merci pour cette réponse, cela le rend beaucoup plus clair. Je ne comprenais pas vraiment très bien les références rvalue. Cela a beaucoup plus de sens que ce que je pensais. – Zifre

12

Parce que l'ajout d'un nouveau type de référence vous permet d'écrire deux surcharges d'une méthode:

void CopyFrom(MyClass &&c) 
{ 
    dataMember.swap(c); 
} 

void CopyFrom(const MyClass &c) 
{ 
    dataMember.copyTheHardWay(c); 
} 

La version qui accepte le nouveau type de référence est autorisé à modifier la variable qu'il reçoit, parce que ISN variables ne va pas être utilisé ailleurs. Donc, il peut "voler" le contenu de celui-ci.

C'est la raison pour laquelle cette fonctionnalité a été ajoutée; le maintien d'un type de référence n'atteindrait pas l'objectif souhaité.