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 :

Retour de fonction par référence?


Sujet :

Langage C++

  1. #1
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 195
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 195
    Points : 17 163
    Points
    17 163
    Par défaut Retour de fonction par référence?
    Bonjour à tous.
    Je suis à la recherche d'un job, et donc, je me retrouve confronté aux tests techniques, dont certaines questions feraient hurler nos compilateurs adorés.

    L'une d'entre elles me tracasse particulièrement:

    supposant une classe Complexe représentant un nombre complexe.
    Choisissez la meilleur implémentation de l'addition:
    1. Complexe& operator+(Complexe const & a, Complexe const & b) {return Complexe(a.re+b.re, a.im+b.im);}
    2. Complexe& operator+(Complexe const * a, Complexe const * b) {return Complexe(a->re+b->re, a->im+b->im);}
    3. Complexe* operator+(Complexe const & a, Complexe const & b) {return new Complexe(a.re+b.re, a.im+b.im);}
    4. Complexe* operator+(Complexe const * a, Complexe const * b) {return new Complexe(a->re+b->re, a->im+b->im);}

    J'aurai personnellement définit:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Complexe operator+(Complexe const & a, Complexe const & b) {Complexe c(a); return c+=b;}
    Complexe& Complexe::operator+=(Complexe const& other) {re+=other.re; im+=other.im;}
    ou encore, si on veut rester concis (mais il faut être friend...)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Complexe operator+(Complexe const & a, Complexe const & b) {return Complexe(a.re+b.re, a.im+b.im);}
    Dans le même genre, une autre fois je trouve int& f(int a, int b) {return a+b;}Je croyais qu'on ne devait jamais retourner une référence sur une constante ou une temporaire…

    Qu'en pensez-vous? Suis-je dans l'erreur?

  2. #2
    Expert confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Points : 4 442
    Points
    4 442
    Par défaut
    Hello,
    Citation Envoyé par leternel Voir le message
    J'aurai personnellement définit:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Complexe operator+(Complexe const & a, Complexe const & b) {Complexe c(a); return c+=b;}
    Complexe& Complexe::operator+=(Complexe const& other) {re+=other.re; im+=other.im;}
    Pareil.

    Parmis les 4 solutions proposées :
    • la première et la deuxième retournent une ref sur un temporaire et sont donc fausses.
    • La troisième et la quatrième génèrent des fuites mémoire si on fait pas attention et sont chiantes à utiliser.
    • De plus la quatrième redéfini l'opérateur+ sur des pointeurs : à éviter.

    S'il faut vraiment choisir dans cette liste, je prendrais la 3eme. Bien que ce soit un enfer à utiliser.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Complexe a, b, c;
    Complexe *d = *(a+b) + c; // (a+b) est perdu, ne peut pas être libéré.
    delete d;
    Mais la seule solution valide est : std::complex.

  3. #3
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 128
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 128
    Points : 33 049
    Points
    33 049
    Billets dans le blog
    4
    Par défaut
    Bonsoir,

    tu as quelques erreurs de recopie dans les codes que tu présentes trop de ; pas assez de , et ) par exemple^^

    Sinon : http://en.wikipedia.org/wiki/Operators_in_C_and_C%2B%2B

    Les opérateur +-*/ ne peuvent pas retourner une référence ! (sauf cas super particulier/spécifique où l'opération modifierait un object déjà existant [pool, static ?] et le retournerait)
    Retourner la référence d'un temporaire est interdit.
    En sortie de fonction, la variable est détruite, et ta référence, fait référence à ... un joli paquet de bits qui vont joyeusement faire crasher ton application.
    Remplace la référence par un pointeur, rajoute un & devant le type de retour, tu as exactement le même résultat, mais ça semble bien plus flagrant que c'est pas à faire je trouve.

    Retourner un pointeur, "pourquoi pas", en tous cas rien ne l'interdit, sauf le bon sens à priori.
    Ca compilerait surement, tant que tu n'essaye pas de chaîner des opérations (sinon, tu vas aussi devoir définir les opérateurs utilisant un pointeur sur le type en question - rappel : il est impossible de définir une opération entre 2 pointeurs).

    M'est avis que si tu as trouvé ces 4 exemples sur des "tests" de boites, vaut mieux éviter la boite en question. En tous cas c'est ce que je ferais

  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
    Points : 16 213
    Points
    16 213
    Par défaut
    Citation Envoyé par leternel Voir le message
    Qu'en pensez-vous?
    J'ai toujours pensé que les tests comme les entretiens servaient autant à un candidat pour tester la boîte qu'à la boîte pour tester le candidat...

  5. #5
    Membre émérite
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 764
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 764
    Points : 2 705
    Points
    2 705
    Par défaut
    Citation Envoyé par Bousk Voir le message
    M'est avis que si tu as trouvé ces 4 exemples sur des "tests" de boites, vaut mieux éviter la boite en question. En tous cas c'est ce que je ferais
    Peut-être que la boîte en question attendait comme réponse "aucune des 4", et attendait une proposition.
    Il faut voir sous quelle forme se présentait la question (et la zone de réponse).

  6. #6
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 195
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 195
    Points : 17 163
    Points
    17 163
    Par défaut
    La question était explicitement un QCM, et effectivement, ils sont disqualifiés à mes yeux.

    Vous me rassurez, j'avais fini par avoir un doute sur mes connaissances.
    Il n'y a pas de prolongation de durée de vie par les références, donc pas de temporaires possibles.

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 381
    Points : 41 581
    Points
    41 581
    Par défaut
    Ça me rappelle mon prof de C qui, dans son spécial "cours de C++", nous avait présenté un "operator+" qui était en fait un opérateur +=...

  8. #8
    Invité
    Invité(e)
    Par défaut
    Tu aurais pu leur signaler qu'ils avaient oublié bien évidemment les opérator + mélangeant en entrée des références et pointeurs et on aurait tout eu

  9. #9
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 128
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 128
    Points : 33 049
    Points
    33 049
    Billets dans le blog
    4
    Par défaut
    Citation Envoyé par Boumbata Voir le message
    Tu aurais pu leur signaler qu'ils avaient oublié bien évidemment les opérator + mélangeant en entrée des références et pointeurs et on aurait tout eu
    C'est parfaitement légal et utilisé http://www.cplusplus.com/reference/s...ing/operator+/
    Sinon, je vois pas de quoi tu parles.

  10. #10
    Invité
    Invité(e)
    Par défaut
    non mais oui je parlais de conserver les ref/pointeurs en sortie en intervertissant les entrées tststsss

  11. #11
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Citation Envoyé par leternel Voir le message
    L'une d'entre elles me tracasse particulièrement:
    Il n'y a qu'une proposition qui compile (la 3), c'est donc la meilleure, mais si elle n'est pas bonne du tout.

    J'aurai personnellement définit:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Complexe operator+(Complexe const & a, Complexe const & b) {Complexe c(a); return c+=b;}
    Complexe& Complexe::operator+=(Complexe const& other) {re+=other.re; im+=other.im;}
    ou encore, si on veut rester concis (mais il faut être friend...)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Complexe operator+(Complexe const & a, Complexe const & b) {return Complexe(a.re+b.re, a.im+b.im);}
    Mon premier réflexe est d'implémenter les @= à partir des @, pas l'inverse qui se retrouve souvent piègeux (le a @= a qui ne fait pas ce qu'il faut est un classique).

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 381
    Points : 41 581
    Points
    41 581
    Par défaut
    Citation Envoyé par Jean-Marc.Bourguet Voir le message
    Mon premier réflexe est d'implémenter les @= à partir des @, pas l'inverse qui se retrouve souvent piègeux (le a @= a qui ne fait pas ce qu'il faut est un classique).
    Peux-tu développer là-dessus?

    Edit: Ah non, je crois que je vois ce que tu veux dire. En gros, tu implémentes le @= à partir de @ et swap?

  13. #13
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 128
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 128
    Points : 33 049
    Points
    33 049
    Billets dans le blog
    4
    Par défaut
    Je crois qu'il parle de ça
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    struct T {
    int a;
    T& operator+=(const T& _r) { a += _r.a; return *this; }
    T operator+(const T& _r) { r(*this); r += _r; return r; }
    };

  14. #14
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    Edit: Ah non, je crois que je vois ce que tu veux dire. En gros, tu implémentes le @= à partir de @ et swap?
    C'est mon premier réflexe. C'est moins piégeux que l'alias possible entre this et le paramètre.

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 381
    Points : 41 581
    Points
    41 581
    Par défaut
    Ah en effet, je n'y avais jamais pensé. J'y pensais pour l'opérateur= (jusqu'à ce que je découvre les joies du copy-and-swap), mais je n'avais jamais réalisé que les opérateurs @= étaient eux aussi exposés à de l'auto-affectation...

  16. #16
    Membre éprouvé
    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mars 2009
    Messages
    552
    Détails du profil
    Informations personnelles :
    Localisation : France

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

    Informations forums :
    Inscription : Mars 2009
    Messages : 552
    Points : 1 060
    Points
    1 060
    Par défaut
    Bonjour,

    Ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Complexe& Complexe::operator+=(Complexe const& other) {re+=other.re; im+=other.im;}
    devrait être :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Complexe& Complexe::operator+=(Complexe const& other) {re+=other.re; im+=other.im; return *this; }

  17. #17
    Membre éclairé

    Profil pro
    Inscrit en
    Décembre 2013
    Messages
    397
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2013
    Messages : 397
    Points : 698
    Points
    698
    Par défaut
    Il n'y a pas de problème d'alias avec @=. La forme canonique (depuis un article de Koening je crois) pour l'implémentation des opérateurs, c'est celle donnée par leternel avec la correction de bretus
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Complexe operator+(Complexe const & a, Complexe const & b) { Complexe c(a); return c+=b; }
    Complexe& Complexe::operator+=(Complexe const& other) { re+=other.re; im+=other.im; reutrn *this; }
    Il y a une discussion, je ne sais plus où (peut être Sutter), sur l'opérateur +, qui peut être écrit selon 2 formes (de mémoire, la seconde est recommandée) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Complexe operator+(Complexe const & a, Complexe const & b) { Complexe c(a); return c+=b; } // création d'un temporaire
    Complexe operator+(Complexe a, Complexe const & b) { return a+=b; } // passage par copie
    Cf http://en.cppreference.com/w/cpp/language/operators (en particulier la partie Binary arithmetic operators)

    @bousk
    l'opérateur + ne doit pas être membre

  18. #18
    Membre expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2011
    Messages
    745
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

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

    Informations forums :
    Inscription : Juin 2011
    Messages : 745
    Points : 3 660
    Points
    3 660
    Par défaut
    Personnellement je ne recommande pas de faire `return a+=b`. Ça à la fâcheuse tendance de désactiver la RVO ou de faire un copy-ctor plutôt plutôt qu'un move-ctor. Il vaut mieux le faire en 2 étapes.

    Je n'ai pas comprit l'histoire d'alias, c'est quoi ?

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 381
    Points : 41 581
    Points
    41 581
    Par défaut
    En gros, c'est un risque de problème quand tu fais a = a ou a += a.

    Exemple volontairement exagéré:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    MyString& MyString::operator+=(MyString const &right)
    {
    	m_pchars = realloc(m_pchars, m_length + right.m_length +1);
    	size_t oldLength = m_length;
    	m_length += right.m_length;
    	std::copy(right.m_pchars, right.m_pchars+right.m_length, m_pchars+oldLength);//oups!
    }

  20. #20
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 128
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 128
    Points : 33 049
    Points
    33 049
    Billets dans le blog
    4
    Par défaut
    Citation Envoyé par mintho carmo Voir le message
    l'opérateur + ne doit pas être membre
    Sauf si tu veux une opération dont l'ordre des opérandes importe (je sais plus le termr, la multiplication matricielle par exemple) / interdire un certain ordre

Discussions similaires

  1. Passage par référence et retour de fonction
    Par mister3957 dans le forum Langage
    Réponses: 2
    Dernier message: 16/05/2015, 13h12
  2. Reference et retour de fonction par valeur
    Par shadowsam dans le forum C++
    Réponses: 4
    Dernier message: 19/03/2011, 17h39
  3. Référence en retour de fonction, à transformer en hash
    Par raoulchatigre dans le forum Langage
    Réponses: 4
    Dernier message: 15/07/2005, 14h24
  4. retour d'objet par référence...
    Par sas dans le forum C++
    Réponses: 15
    Dernier message: 28/05/2005, 17h54
  5. Réponses: 10
    Dernier message: 03/03/2005, 13h36

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