Pages

dimanche 17 mars 2013

Ne pas empêcher la NRVO

La NRVO et la RVO sont des optimisations des compilateurs pour retourner un objet sans le copier. Je renvoie directement sur une partie de la FAQ C++ de développez.com: d'ici jusqu'à la fin.

Cependant ces optimisations ne s'appliquent pas lorsqu'un appel de méthode qui retourne son instance est directement retourné (une référence sur elle-même).
Ceci:

S f()
{
  S ret;
  return ret.action(); //S& action() { /*...*/ return *this; }
}

Ou cela:

iterator operator+(const iterator& other, int n)
{ return iterator(other) += n; }

Dans ces 2 exemples l'objet est copié inutilement. Pour éviter cette copie, il faut décomposer le code pour que le retour de la fonction ne soit pas lié à une méthode: il faut retourner explicitement l'objet. Ainsi la variable de retour est une variable nommée et la NRVO s'applique.

S f()
{
  S ret;
  ret.action();
  return ret;
}

Et cela:

iterator operator+(const iterator& other, int n)
{
  iterator ret(other);
  ret += n;
  return ret;
}

C'est une optimisation facile à faire et il est tout aussi facile de passer à côté ;).

5 commentaires:

Anonyme a dit…

Pourquoi il ne fait pas cette optimisation dans ce cas ?

Jonathan Poelen a dit…

Je ne suis pas sûr, mais je pense que le compilateur ne regarde pas l'implémentation de la fonction appelé (dans l'exemple S::action()) mais juste le type de retour. Et comme le type de retour ne correspond pas forcément à l'objet appelant, dans le doute, une copie est faite.

Anonyme a dit…

très bon article!!!!

Blanchet Florian a dit…

Bonjour,

C'est totalement normal qu'il n'optimise pas tes premiers codes. Les expressions ne sont pas des temporaires (le retour des fonctions utilisées et T& et non T), ce n'est pas un cas d'élision.

Jonathan Poelen a dit…

C'est vrai, mais je trouve dommage que les compilateurs n'essayent pas de 'comprendre' la source pour justement faire cette optimisation quand une référence est retourné.
Bien sûr, ça obligerait de connaître l'implémentation de la fonction. Des fois le compilateurs ne pourrait pas le faire et surtout on ne serait pas en mesure de le savoir.