Question

L'une des nouvelles fonctionnalités cool de la prochaine norme C ++, C ++ 0x, sont les «références de référence». Une référence de la valeur est similaire à une référence Lvalue (normale), sauf qu'elle peut être liée à une valeur temporaire (normalement, un temporaire ne peut être lié qu'à un const référence):

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

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

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

Était-ce utile?

La solution

Ce serait inutile.Vous modifieriez la chose dans la fonction, et la modification serait immédiatement perdue car la chose était en fait temporaire.

La raison de ce nouveau type vient de la nécessité de pouvoir décider ce qui est réellement une rvalue et ce qui ne l'est pas.Ce n'est qu'alors que vous pourrez réellement les utiliser pour les choses intéressantes 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 une valeur r et que vous la transmettez à toupper, la valeur r peut être directement modifiée, car nous savons que le temporaire est de toute façon une chose jetable, nous pouvons donc également simplement la modifier sans avoir besoin de la copier.En outre, la même observation est utilisée pour ce qu'on appelle les constructeurs de mouvements et l'affectation de mouvements.Le côté droit n'est pas copié, mais ses éléments sont simplement volés et déplacés vers *this.

Si vous deviez dire que les rvalues ​​peuvent se lier à des références lvalue non const, alors vous n'auriez aucun moyen de savoir si cela fait référence à une lvalue (objet nommé) ou à une rvalue (temporaire) à la fin.


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

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

Maintenant, tu ne peux plus dire

string() = "hello";

Ce qui est déroutant et n’a pas vraiment de sens la plupart du temps.Qu'est-ce que & ci-dessus dit que l'opérateur d'affectation ne peut être invoqué que sur les lvalues.La même chose peut être faite pour les rvalues, en mettant &&.

Autres conseils

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ée à modifier la variable reçue car cette variable ne sera utilisée nulle part ailleurs. Donc, il peut & "Voler" & "; le contenu de celui-ci.

C’est la raison pour laquelle cette fonctionnalité a été ajoutée; conserver un type de référence ne permettrait pas d'atteindre l'objectif souhaité.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top