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 :

Retour référence d'un paramètre


Sujet :

C++

  1. #1
    Expert éminent sénior
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 630
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 630
    Points : 10 556
    Points
    10 556
    Par défaut Retour référence d'un paramètre
    Bonjour,

    J'ai passé un test chez IT&M aujourd'hui (ils sont basés à Neuilly-sur-Seine).

    Et autre le fait que j'ai appris certaines choses en C++ (si j'ai bien vu les réponses ) comme les templates ne respectent pas le principe de réécriture, que l'héritage en diamant se résout soit avec l'héritage virtuel soit avec l'héritage privé, que List ne permet pas de stocker des objets hétérogènes.
    Mais surtout il y a 2 questions qui me scotchent totalement

    Pour la petite histoire c'est la deuxième fois que je vais à IT&M, avec le même test, les mêmes interrogations et ... avec toujours autant de fautes d’orthographes (calsses, pr, propiété, cela dépends, ...)

    C'est 2 fois la même question mais avec une fonction différente
    Il faut dire si les fonctions 1) compilent 2) ne compilent pas 3) créent des fuites mémoire 4) cela dépend du compilateur
    1. Code : Sélectionner tout - Visualiser dans une fenêtre à part
      int& meth(int& a) { return ++a; }
    2. Code : Sélectionner tout - Visualiser dans une fenêtre à part
      int& meth(int a)  { return ++a; }


    • Pour la fonction 1, on retourne le paramètre: sûrement un besoin de chaîner les appels. La réponse que j'ai réussi à voir (si j'ai bien vu) est 2) ne compile pas
    • Pour la fonction 2, on retourne une référence sur un objet local. La réponse que j'ai réussi à voir (si j'ai bien vu) est 1) compile


    J'ai sorti mes compilateurs et
    • avec g++ 4.8.3 (sous Cygwin) cela fonctionne correctement, mais tu peux réussir à avoir des valeurs farfelues (avec 2 affichages consécutifs)
    • avec Visual C++ 2010, cela ne fonctionne pas correctement, mais cela ne plante pas du tout.



    Donc voila la question que je pose, parce que cela ne plante pas: est-ce qu'il faut soit voir une espèce d'optimisation style RVO soit rien du tout avec du code aussi minimaliste [pauvre] soit je m'y prends mal.

    Ou alors, cela vient des références


    Voici mes tests succincts:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    #include<iostream>
    #include<cstdio>
     
    int& meth1(int& a) { return ++a; }
    int& meth2(int a)  { return ++a; } // attention : reference to local variable ‘a’ returned [-Wreturn-local-addr]
    //int& meth3(int& a) { return a++; } // error C2440: 'return' : cannot convert from 'int' to 'int &'
    //int& meth4(int a)  { return a++; } // error C2440: 'return' : cannot convert from 'int' to 'int &'
     
     
    using namespace std;
     
     
    int main(int argc, char* argv[])
    {
    /*********************************** Meth1 ***********************************/
        int a = 95;
        int b = meth1(a);
     
    //  result: meth1(96): 96
        cout << "meth1(" << a << "): " << b << endl;
     
        int& c = meth1(a);
        c = 10;
        b = 57;
     
    //  result: meth1(10): 10, b: 57
        cout << "meth1(" << a << "): " << c << ", b: " << b << endl;
     
     
    /*********************************** Meth2 ***********************************/
        int d = meth2(b);
     
    //  result: meth2(57): 58
        cout << "meth2(" << b << "): " << d << endl;
     
        int& e = meth2(b);
    //  d = 57;
        d = e + 15;
     
    //  result: "meth2(57): 10, d: 57" or "meth2(57): 1582238320, d: 57"
    //  cout << "meth2(" << b << "): " << e << ", d: " << d << endl;
     
    //  result: "meth2(57): 58, d: 57" ou "meth2(57): 57, d: 57"
        printf("meth2(%d): %d, d:%d\n", b, e, d);
     
    //  d = e + 15;
    //  printf("meth2(%d): %d, d:%d\n", b, e, d);
     
        e = 92;
     
    //  result: "e: 92" ou "e: 1582238320"
    //  cout << "e: " << e << endl;
     
    //  result: "e: 92"
        printf("e: %d\n", e);
     
        return 0;
    }

  2. #2
    Membre émérite

    Inscrit en
    Mai 2008
    Messages
    1 014
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 1 014
    Points : 2 252
    Points
    2 252
    Par défaut
    Faut toujours se méfier des tests C++ donnés par les boites, surtout quand ils se targuent d’arborer des détails très précis, il y a parfois des erreurs flagrantes et c'est souvent confus. C'est parfois plus un exercice en psychologie pour comprendre où le rédacteur a voulu en venir

    Pour les deux fonctions meth, sans trop réfléchir j'aurais tendance à dire :
    1) compile si l'on passe une lvalue, ne compile pas sinon
    2) compile, mais comportement indéterminé

    Et effectivement ça ne colle pas vraiment avec les choix proposées...

    Et autre le fait que j'ai appris certaines choses en C++ [...] que List ne permet pas de stocker des objets hétérogènes.
    ça par contre je ne vois pas trop pourquoi ça te surprend ? Si on parle bien de std::list<T> effectivement il ne peut pas stocker des types hétérogènes, uniquement T, mais comme tous les autres conteneurs de la STL en fait ?

    Edit : "les templates ne respectent pas le principe de réécriture"
    Jamais entendu parler du "principe de réécriture" C'est quoi ?

  3. #3
    Expert éminent sénior
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 630
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 630
    Points : 10 556
    Points
    10 556
    Par défaut
    Citation Envoyé par Arzar Voir le message
    1) compile si l'on passe une lvalue, ne compile pas sinon
    Effectivement vu sous cet angle ... si on a affaire à un mauvais développeur: Pourquoi meth1(5) ne compile pas?

    Une question vague pour un cas précis


    Citation Envoyé par Arzar Voir le message
    ça par contre je ne vois pas trop pourquoi ça te surprend ? Si on parle bien de std::list<T> effectivement il ne peut pas stocker des types hétérogènes, uniquement T, mais comme tous les autres conteneurs de la STL en fait ?
    Je me suis fait avoir ou
    Effectivement dans une collection le type est homogène (à moins de bidouiller avec void* si on y arrive) mais on peut créer des collections de type hétérogènes

    Je vais bientôt venir aux entretiens avec un dictionnaire et de l'aspirine


    Citation Envoyé par Arzar Voir le message
    Jamais entendu parler du "principe de réécriture" C'est quoi ?
    Justement je me demande si la personne qui a écrit le test n'a pas balancé un terme bidon/ qui n'existe pas mais dont l'écriture/ les mots peuvent supposer quelque chose.

    Et biiiiiiim!!!... 1 chance sur 2 de se bourrer ou

  4. #4
    Rédacteur/Modérateur


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

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Y'a rien de vraiment extraordinaire, c'est typiquement un test inutile pour t'embrouiller (mais moins ridicule que ceux que j'avais passé dans d'autres SSII tiens)

    il n'a jamais été interdit de retourner une référence, il faut juste que la référence retournée soit "valide". ca compilera toujours, même si tu retournes une référence d'un temporaire, avec un warning dans le meilleur des cas

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    #include <iostream>
    int& m1(int& a) { return ++a; }
    int& m2(int a) { return ++a; }
    void main()
    {
    	int a = 5;
    	int b = m1(a);
    	int c = m2(a);
    	std::cout << "a:" << a << "; b:" << b << "; c:" << c << std::endl;
    	int& aa = a;
    	int& ab = m1(a);
    	int& ac = m2(a);
    	a = 100;
    	b = 200;
    	c = 300;
    	std::cout << "a:" << a << "; b:" << b << "; c:" << c << std::endl;
    	std::cout << "aa:" << aa << "; ab:" << ab << "; ac:" << ac << std::endl;
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    a:6; b:6; c:7
    a:100; b:200; c:300
    aa:100; ab:100; ac:19207269
    dans l'ordre, on déclare a
    puis on incrémente a et b qui est une copie valant a (après incrémentation)
    puis c est une copie qui vaut a, puis on incrémente a
    ensuite, aa et ab sont des références sur a, ac est indéterminé

    Pourquoi meth1(5) ne compile pas?
    parce qu'il est interdit de passer par référence un litéral, il faut le passer par const&
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  5. #5
    Expert éminent sénior
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 630
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 630
    Points : 10 556
    Points
    10 556
    Par défaut
    Après réflexion et avec vos réponses, les réponses de la petite dizaine de questions (dont les réponses des 2 questions de ce fil) (*) parmi 27 qui me semblaient litigieuses/ surprenantes sont correctes.
    Mais beurk

    Donc pour les 2 questions, la fonction 1 ne compile pas et la fonction 2 compile (si j'ai bien vu les réponses )
    Mais une furieuse impression que:

    1) La réponse est biaisée/ l'auteur a dit "c'est cette réponse".
    Pourquoi s’intéresser au passage lvalue/ rvalue, dont la question ne comporte pas de notions. Si on veut qu'une fonction ne compile on peut aussi passer un type inapproprié, réduire sa visibilité, la mettre dans la namespace....
    L'auteur a dit "fonction 1 ne compile pas" point barre
    D'autant plus que la fonction 2 devrait générer un warning, mais sur cela silence.

    2) L'auteur oriente la réponse. Parce que la question est bel et bien "Compile ou pas" et non pas "fonction crasseuse ou pas"
    Notamment avec la réponse 3: "fuite mémoire" ou le choix des fonctions pour la réponse (une fonction gentille qui ne doit pas compiler et une fonction méchante qui doit compiler)

    D'ailleurs, le retour de la variable locale n'est pas forcément évident, puisque ce n'est pas un retour d'une variable explicitement créée dans la fonction, mais de la copie du paramètre (il faut noter au passage le retour ++a obligatoire et non pas a++).
    C'est pour cela qu'à la connaissance des réponses, il m'a semblé y avoir une optimisation RVO ou autre

    Donc, en gros, un gars qui fait attention à cela (et qui prend ce test pour ce qu'il est, un test technique) a plus de chance de se faire avoir


    Je note juste (mais est-ce que cela est pertinent avec du code aussi trivial?), que les références C++ ne plantent pas, mais créent des valeurs farfelues
    On m'a toujours dit: "Il faut mieux que ton code plante, au lieu qu'il fonctionne avec des valeurs farfelues et/ ou qui plante ailleurs"


    Citation Envoyé par Bousk Voir le message
    parce qu'il est interdit de passer par référence un litéral, il faut le passer par const&
    Dans le cas de ces 2 fonctions, cela va être un peu difficile


    * -> Il y avait une question "c'est quoi inline", à laquelle j'ai eu 1/2 point en répondant "l'appel de la fonction sera remplacée par le code"
    Et, en y pensant, il me semble que la deuxième réponse (pour avoir 1 point) est "l'appel de la fonction appellera le code"

    Évidemment, un verre à moitié plein et à la fois "à moitié plein" et "à moitié vide"
    Pour la question "inline" j'avais trouvé justement très impartiale cette réponse pour "un conseil au compilateur": je comprends maintenant

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

Discussions similaires

  1. Réponses: 3
    Dernier message: 27/02/2012, 17h52
  2. Biblio multiples- retour à référence n°1
    Par emorejbleu dans le forum Bibliographies - Index - Glossaires
    Réponses: 8
    Dernier message: 26/05/2011, 14h18
  3. Réponses: 4
    Dernier message: 28/10/2010, 10h21
  4. Retour d'objet générique / paramétré
    Par Jabbal'H dans le forum Langage
    Réponses: 4
    Dernier message: 03/04/2008, 15h31
  5. Réponses: 2
    Dernier message: 24/08/2007, 01h54

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