web-dev-qa-db-fra.com

Le retour par référence rvalue est-il plus efficace?

par exemple:

Beta_ab&&
Beta::toAB() const {
    return move(Beta_ab(1, 1));
}
118
Neil G
Beta_ab&&
Beta::toAB() const {
    return move(Beta_ab(1, 1));
}

Cela renvoie une référence pendante, tout comme avec le cas de référence lvalue. Après le retour de la fonction, l'objet temporaire sera détruit. Vous devez renvoyer Beta_ab Par valeur, comme suit

Beta_ab
Beta::toAB() const {
    return Beta_ab(1, 1);
}

Maintenant, il déplace correctement un objet Beta_ab Temporaire dans la valeur de retour de la fonction. Si le compilateur le peut, il évitera complètement le déplacement, en utilisant RVO (optimisation de la valeur de retour). Maintenant, vous pouvez faire ce qui suit

Beta_ab ab = others.toAB();

Et il déplacera la construction du temporaire dans ab, ou fera RVO pour omettre de faire un déplacement ou une copie. Je vous recommande de lire BoostCon09 Rvalue References 101 qui explique le problème et comment (N) RVO arrive à interagir avec cela.


Votre cas de renvoi d'une référence rvalue serait une bonne idée dans d'autres occasions. Imaginez que vous ayez une fonction getAB() que vous invoquez souvent de façon temporaire. Il n'est pas optimal de lui faire renvoyer une référence const lvalue pour les valeurs temporaires rvalue. Vous pouvez l'implémenter comme ceci

struct Beta {
  Beta_ab ab;
  Beta_ab const& getAB() const& { return ab; }
  Beta_ab && getAB() && { return move(ab); }
};

Notez que move dans ce cas n'est pas facultatif, car ab n'est ni une valeur locale automatique ni une valeur r temporaire. Maintenant, le qualificatif ref && Indique que la deuxième fonction est invoquée sur les valeurs temporaires rvalue, faisant le mouvement suivant, au lieu de copier

Beta_ab ab = Beta().getAB();
216

Il peut être plus efficace, par exemple, dans un contexte un peu différent:

template <typename T>
T&& min_(T&& a, T &&b) {
    return std::move(a < b? a: b);
}

int main() {
   const std::string s = min_(std::string("A"), std::string("B"));
   fprintf(stderr, "min: %s\n", s.c_str());
   return 0;
}

Comme observation intéressante, sur ma machine clang++ -O3 Génère 54 instructions pour le code ci-dessus contre 62 instructions pour le std::min Normal. Cependant, avec -O0, Il génère 518 instructions pour le code ci-dessus contre 481 pour le std::min Normal.

3
wonder.mice