IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

Reference et retour de fonction par valeur


Sujet :

C++

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    99
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 99
    Points : 102
    Points
    102
    Par défaut Reference et retour de fonction par valeur
    Bonjour,

    Je suis tombé il y a quelques jours sur un blog qui montrait, dans son exemple sur les références le code suivant:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    class Retour
    {
    public:
       void g() const {}
    };
     
    Retour f() { return Retour(); }
     
    int main(int argc, char *argv[])
    {
        const Retour &retour = f();
        retour.g();
        return 0;
    }
    Le blog expliquait que l'assignation de la variable de retour de la fonction a une référence permettait de s'alléger d'une copie.

    Je ne trouve aucune autre références à cette pratique sur le net et n'ai rien lu non plus qui parle de cela dans les bouquins de Sutter/Meyers qui parlent des bonnes pratiques.

    Je me demande donc si cette optimisation est vraiment une bonne pratique, selon vous ?

  2. #2
    Membre averti Avatar de Flo.
    Homme Profil pro
    Inscrit en
    Mai 2002
    Messages
    379
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mai 2002
    Messages : 379
    Points : 404
    Points
    404
    Par défaut
    Alors si j'ai tout bien compris du c/c++ ... (ce qu'est pas dit)

    Il y a un premier objet de type Retour créé ici

    Comme la fonction retourne l'objet par valeur, un deuxième objet est créé et copié à partir du premier.

    Ensuite si tu fais

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    const Retour retour = f();
    alors un troisième objet de type Retour est créé puis copié à partir du deuxième. Alors que si tu fais :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    const Retour & retour = f();
    Il n'y a pas de troisième objet créé ni même copié mais la référence de l'objet retourné par la fonction est stocké dans la référence retour.

    Les constructeurs par déplacement à venir (si j'ai tout bien compris encore) pourront réduire le nombre de créations/copies dans les 2 cas de 1.

    Flo.

    Voilà

  3. #3
    Membre expérimenté
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mars 2011
    Messages
    576
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2011
    Messages : 576
    Points : 1 528
    Points
    1 528
    Par défaut
    Cela évite bien une recopie mais ne risque-t-on pas de faire une référence vers un objet qui vas être dépiler ? En cascadant les fonction du genre:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    Retour f(){ return Retour(); }
     
    void h(Retour& r){ r = f(); }
     
    int main(){
      Retour r;
      h(r);
      // Ici, r serait une référence vers une variable local de f, donc qui n'existe plus...
    }
    Ce code ne compile pas mais c'est pour montrer l'idée. (En remplaçant les ref par des pointeurs, ça compile et ça montre parfaitement pourquoi les pointeurs sont dangereux ).
    La perfection est atteinte, non pas lorsqu’il n’y a plus rien à ajouter, mais lorsqu’il n’y a plus rien à retirer. - Antoine de Saint-Exupéry

  4. #4
    screetch
    Invité(e)
    Par défaut
    j'ai beau tester avec différents compilateurs et avec du code a effet de bord, le code que tu montres n'effectue pas de copie sur sunCC, gcc et msvc.

  5. #5
    En attente de confirmation mail

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Points : 3 311
    Points
    3 311
    Par défaut
    Oui c'est tout à fait normal.

    Dans le cas normal il devrait y avoir :
    - Construction dans le scope de la fonction
    - Copie dans un objet temporaire hors du scope de la fonction
    - Affectation à une référence constante (le consante est important car c'est un objet temporaire).

    Or il y a des règles (nommées copy-elision dans la norme, et souvent distingués en 3 catégorie)

    - (N)RVO : (Le N c'est pour Named) Permet au compilateur de construire directement l'objet dans l'objet temporaire hors du scope de la function si celui ci a le même type de base que le type de retour

    - Copy-Elision : Permet au compilateur de construire directement dans un objet qui devrait être copié depuis un temporaire quand ceux-ci ont le même type de base.

    Marche aussi pour la move-semantic (et cf norme pour les détails, il y a d'autre cas de cette règle plus spécifique).

    Dans ton cas c'est la première règle qui s'applique, si tu enlèves la référence constante et tu verras qu'il n'y a aussi qu'une construction, la seconde règle se combine ainsi à la première.

    A noter que le compilateur PEUT faire ces optimisation mais qu'il n'est pas obligé de les faire. Cependant ca a une incidence sur notre facon de coder : il ne faut pas que nos constructeur de copie / destructeur (/move-ctor) aient des effets de bord, ie qu'il ne fasse pas autre chose que copier/détruire, sinon l'optimisation du compilateur risque d'avoir des effets inatendues sur notre code.

Discussions similaires

  1. Retour de fonction par référence?
    Par ternel dans le forum Langage
    Réponses: 27
    Dernier message: 10/05/2014, 18h17
  2. Réponses: 2
    Dernier message: 09/12/2010, 20h52
  3. [POO] Retour de données par une fonction (return)
    Par webrider dans le forum Langage
    Réponses: 6
    Dernier message: 26/08/2006, 21h49
  4. Fonctions et valeur par default
    Par Goundy dans le forum C
    Réponses: 5
    Dernier message: 27/02/2006, 22h16
  5. fonction operator, valeur de retour
    Par butch dans le forum C++
    Réponses: 21
    Dernier message: 20/09/2004, 10h30

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo