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

Langage C++ Discussion :

différences entre const double& et double


Sujet :

Langage C++

  1. #1
    Membre confirmé Avatar de BigNic
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    195
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Décembre 2004
    Messages : 195
    Par défaut différences entre const double& et double
    bonjour,
    si je considère deux versions d'un accesseur:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    double GetValue const {return m_dValue;}
    et
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    const double& GetValue const {return m_dValue;}
    quelles sont les différences entre les deux, notamment en terme de performance et de threading, ma donnée membre m_dValue pouvant être modifié et lue pard des threads différents.
    quid de l'usage de lock avec des critical section ou du mot clé volatile

    Je me demande quelle implémentation est la meilleure.

    Je précise que je suis en MS VS 2009 et que ce qui m’intéresse c'est le mode release.

  2. #2
    Membre très actif
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2010
    Messages
    254
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2010
    Messages : 254
    Par défaut
    La différence est que dans ton premier exemple, ton accesseur renvoie une copie de ton double, ce qui veut dire que ton programme va allouer une nouvelle variable.

    Dans ton deuxième exemple tu renvoie une référence, ce qui veut dire que la variable ne sera pas copié mais que ce sera sont adresse qui sera directement transmise, un peu comme un pointeur. Il n'y a donc pas de duplication de variable.

    L'interet du const est que comme c'est un accès direct à la variable que tu renvoie, et non pas une copie, si la variable est modifiée, ça modifiera aussi la propriété de l'objet. On met ce const pour que la référence renvoyé ne soit disponible qu'en lecture, histoire que t'ai pas un effet de bord qui foute en l'air tes objets.

    Niveau performance, le passage par référence est plus rapide, car c'est toujours une adresse que tu renvoie (adresse = pointeur = 4 octets). Un passage par copie sera plus lent surtout si la variable que tu passe est un GROS objet bien gras bien velu.

    Dans les deux cas que tu a présenté, la propriété m_dValue de ton objet ne sera pas modifié peut importe ce que tu fait avec. Si tu veux la modifier tu doit faire une fonction membre genre
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    setM_Dvalue(double const & new_value);

  3. #3
    Membre confirmé Avatar de BigNic
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    195
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Décembre 2004
    Messages : 195
    Par défaut
    Merci Marvin pour ta réponse rapide. Elle me montre que j'ai pas assez précisé ma question.
    Ce que tu raconte est de la théorie du langage, et tout est vrai. Mais en réalité une fois optimisé (mode release) est-ce toujours vrai ? Notamment si mon code est dans le header, donc possiblement inline.

  4. #4
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Par défaut
    Il y a une différence de taille en terme de comportement. Si tu stockes le retour de ta fonction dans une référence, et que la valeur interne à ton objet est modifiée après que tu aies appelé ton GetValue, tu verras la nouvelle valeur dans la version par référence, pas dans l'autre.

    Du coup, même si on a un coût de recopie, je pense que celui-ci est probablement inférieur à celui induit par le fait que le compilateur doit gérer ce changement potentiel, et donc a moins de libertés pour réarranger le code.

    Donc en plus d'être plus simple (ce qui est souvent le critère à prendre en compte en priorité), je pense que la solution retournant un double a aussi de bonnes chances d'être plus performante dans un vrai programme.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  5. #5
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 391
    Par défaut
    Pour le coup des performances, la taille d'un double (le plus souvent 8 octets) est généralement la limite au-dessus de laquelle il devient "plus efficace" de minimiser les copies.

    Dans le cas présent, retourner le double "par valeur" est plus simple et devrait être plus efficace. S'il s'était agit d'un type complexe, avec un constructeur de copie complexe (une std::string ou un conteneur, par exemple), retourner une référence peut être plus performant.

    De plus, comme l'a dit JolyLoic, il reste la question de la modification: Quel est le comportement qui surprendra le moins l'utilisateur de la classe? Généralement, c'est la copie.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  6. #6
    screetch
    Invité(e)
    Par défaut
    les double sont des cas particuliers puisqu'ils ne sont pas retournés en mémoire mais dans un registre FPU, il n'y a pas forcément de copie.
    Ca dépend grandement de ce qu'on en fait; dans un cas il faut charger depuis la mémoire vers ST0, dans l'autre on copie l'adresse dans un registre, puis a chaque utilisation (comme la variable peut avoir changé a tout moment) le code client la recharge dans ST0.

    Donc dans un cas on fait une lecture mémoire, dans un autre, on en fait autant de fois qu'on utilise le double.
    Or, la plupart du temps, on copie la valeur de retour dans un double a soi, même quand l'accesseur renvoie une référence:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    const double& GetValue const {return m_dValue;}
     
     
    double d = GetValue();
    ce qui revient en général strictement au même.
    Donc pour conclure, il faut retourner ce qui est le plus naturel et penser a la performance aprés; et il ne faut pas juger la performance a priori, seulement a posteriori.

  7. #7
    Membre confirmé Avatar de BigNic
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    195
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Décembre 2004
    Messages : 195
    Par défaut
    Merci à tous pour vos réponses !

    Le code n'a pas été écris par moi et comme je vais devoir sortir un release qui va changer pas mal de choses fonctionnellement parlant, je faisait du ménage et m’interrogeais sur la pertinence de l'écriture avec les const double&.
    De plus récemment on m'a ouvert un bug sur les perfs du softs et que le but du soft est calculé plein m_dValue et publié vous imaginez bien que sont accesseur est appelé souvent. Donc on est bien à postériori !
    m_dValue est bien un double, pas de class. Pour les classe j'ai bien laissé les accesseur avec une forme const maClasse &.
    Avoir une copie de m_dValue ne me dérange pas, au contraire, un stimuli va lancer son calcul et après je vais devoir la publié donc autant le faire avec la valeur cohérente avec ce stimuli. Et non reprendre la valeur au moment ou je vais devoir la publié, alors qu'un deuxième stimuli l'a encore changé.
    Enfin j'ai pas mal d'endroit ou le code ressemble à ça:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    {
        Mafonction1(pC->GetValue());
        MaFonction2(pC->GetValue());
    }
    donc je pourrais les ré-écrire avec un copie d'abord (cf reponse screetch), mais ça ferait pas mal de boulot.

  8. #8
    screetch
    Invité(e)
    Par défaut
    dans le cas précédent, MaFonction1 et MaFonction2 peuvent être appelées avec des paramètres différents si un uatre thread change la valeur au "mauvais" moment. Et je ne sais pas comment ca va affecter tes calculs, c'est a toi de voir.

    mais si MaFonction1 et MaFonction2 prennent un double en paramètre (et non pas un const double&) alors il n'y a pour ainsi dire aucune différence entre les deux codes.

  9. #9
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 391
    Par défaut
    S'il est question de performance, j'espère que l'accesseur peut être inliné (s'il est déclaré dans la classe, ou défini en inline dans le .h, ou si compilo supporte la Link-Time Code Generation (LTCG) et elle est activée), car un appel de fonction pour un truc si petit prendra plus de temps et d'espace mémoire que simplement lire la valeur..
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Différence entre une association simple et double
    Par antoine2641 dans le forum Merise
    Réponses: 7
    Dernier message: 16/05/2013, 19h30
  2. Réponses: 9
    Dernier message: 28/05/2008, 14h46
  3. différence entre long et double
    Par bolltt dans le forum Macros et VBA Excel
    Réponses: 1
    Dernier message: 25/03/2008, 18h46
  4. différence entre double et float
    Par Maria1505 dans le forum C++
    Réponses: 2
    Dernier message: 03/01/2007, 05h16
  5. Différence entre Integer et double?
    Par Michel DELAVAL dans le forum Access
    Réponses: 15
    Dernier message: 10/02/2006, 15h57

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