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 :

Structure: Retour de méthode


Sujet :

C++

  1. #1
    Candidat au Club
    Profil pro
    Inscrit en
    Septembre 2007
    Messages
    3
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2007
    Messages : 3
    Par défaut Structure: Retour de méthode
    Bonjour,

    Ce code est-il correct ?

    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
     
    struct titi
    {
    	int a;
    	int b;
    };
     
    class toto
    {
    public:
     
    	titi func()
    	{	
    		titi s;
     
    		s.a = 2;
    		s.b = 3;
    		return (s);
    	}
    };
     
     
    int _tmain(int argc, _TCHAR* argv[])
    {
    	toto t;
     
    	titi a = t.func();
     
    	return 0;
    }
    Ou alors je dois donné l'adresse de ma structure en parametre?
    Si je dis pas de betise, dans mon cas, je fais une copie de ma structure donc pas de soucis, non?

    Merci d'avance

  2. #2
    Membre chevronné
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2006
    Messages
    366
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

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

    Informations forums :
    Inscription : Mai 2006
    Messages : 366
    Par défaut
    Oui ça marche. Un simple test aurait pu t'en convaincre (et pas besoin de parenthèses dans le return s)

  3. #3
    Candidat au Club
    Profil pro
    Inscrit en
    Septembre 2007
    Messages
    3
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2007
    Messages : 3
    Par défaut
    Oui mon test marche mais j'ai deux autres questions:

    1/ C'est dans quel cas qu'il faut évité de retourner une adresse local?

    2/ Et est-ce plus optimé de retourné une structure ou de la passé en parametre?

    C'est à dire:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    titi func()
    {
       titi t;
       t.a = 2;
       t.b = 3;
       return (t);
    }
     
    //Appel:
    titi a = func();
    ou

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    void func(titi *t)
    {
       t.a = 2;
       t.b = 3;
    }
     
    //Appel:
    titi a;
    func(&a);
    De plus je comprend pas pourquoi quand je fais:

    dans le premier cas, je rentre qu'une fois dans le contructure de titi

    Merci

  4. #4
    Membre expérimenté Avatar de Kujara
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    262
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Décembre 2006
    Messages : 262
    Par défaut
    Citation Envoyé par abcdefghijk Voir le message
    En theorie pure, passer la structure en parametre est plus optimisé ( permet d'eviter une construction / copie).

    De plus je comprend pas pourquoi quand je fais:
    dans le premier cas, je rentre qu'une fois dans le contructure de titi
    Le compilateur optimise automatiquement dans ce cas la :
    Donc un appel constructeur, puis un appel constructeur par copie, plutot que 2 appels constructeurs plus une copie.

  5. #5
    Candidat au Club
    Profil pro
    Inscrit en
    Septembre 2007
    Messages
    3
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2007
    Messages : 3
    Par défaut
    Merci

    Donc par logique/optimisation il vaut mieux passé la structure en parametre (pointeur) ?

    Et dans ce cas, pointeur ou ref?

  6. #6
    Membre expérimenté Avatar de Kujara
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    262
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Décembre 2006
    Messages : 262
    Par défaut
    Citation Envoyé par abcdefghijk Voir le message
    Merci

    Donc par logique/optimisation il vaut mieux passé la structure en parametre (pointeur) ?

    Et dans ce cas, pointeur ou ref?
    Le pointeur te permet de passer NULL, mais ça te coute un test de plus, justement dans le cas où tu lui passe null ....

    A toi de voir

  7. #7
    Membre éclairé Avatar de befalimpertinent
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    561
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Gironde (Aquitaine)

    Informations forums :
    Inscription : Avril 2007
    Messages : 561
    Par défaut
    je cite la faq
    http://cpp.developpez.com/faq/cpp/in...CE_utilisation
    Utilisez les références aussi souvent que possible, et les pointeurs quand vous le devez.

    Les références sont habituellement préférables aux pointeurs, à moins que vous ne deviez la réallouer à un moment donné.

  8. #8
    screetch
    Invité(e)
    Par défaut
    euh...

    retourner une structure de deux elements par copie est tout a fait envisageable! cela serait en fait aussi rapide que de passer un argument sur la pile.
    Laissez les compilos faire l'optimisation est en general plus malin que d'essayer de faire mieux que lui.

    Il existe des cas particuliers, mais avant de savoir si ca vaut le coup ou pas, il faut s'informer sur la RVO (Return by Value Optimization) effectuee par les compilateurs, et ne s'en soucier que pour les classes/structures avec plus de 5 champs ou avec un constructeur de copie plus complexe.

  9. #9
    Membre éprouvé
    Avatar de NiamorH
    Inscrit en
    Juin 2002
    Messages
    1 309
    Détails du profil
    Informations forums :
    Inscription : Juin 2002
    Messages : 1 309
    Par défaut
    On peut tout a fait se servir du constructeur par copie ici, car on est dans un cas tout a fait particulier : http://en.wikipedia.org/wiki/Plain_Old_Data_Structures

    Mais pour la majorité des class et struct, le mieux est de les passer par référence.

  10. #10
    Membre éclairé Avatar de befalimpertinent
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    561
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Gironde (Aquitaine)

    Informations forums :
    Inscription : Avril 2007
    Messages : 561
    Par défaut
    Citation Envoyé par NiamorH Voir le message
    Mais pour la majorité des class et struct, le mieux est de les passer par référence.
    référence constante bien sur

  11. #11
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Salut,
    Citation Envoyé par befalimpertinent Voir le message
    référence constante bien sur
    ... A condition qu'il ne soit pas question de modifier ce qui est représenté par la référence
    @abcdefghijk ==>
    Il faut faire attention au code:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    void func(titi *t)
    {
       t.a = 2;
       t.b = 3;
    }
    Comme tu passe un pointeur, tu dois utiliser la "fleche"
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    void func(titi *t)
    {
       t->a = 2;
       t->b = 3;
    }
    Ce qui est surtout dangereux, c'est une fonction du genre de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    class toto
    {
        public:
            /*const*/ titi& fonct() /*const*/;
            /*voir */
            /*const*/ titi* fonct2() /*const*/;
            /*...*/
    };
    (les "const" en commentaires étant là pour dire que leur présence ou leur absence ne change rien au problème

    Si la variable est un membre de la classe (ex
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    class toto
    {
        public:
            /*const*/ titi& fonct() /*const*/{return t;}
            /* ou */
            /*const*/ titi* fonct2() /*const*/{return &t;}
            /*...*/
        private:
            titi t;
    };
    il n'y aura aucun problème: tant que l'instance de type "toto" auprès de laquelle on a récupéré le membre de type titi et nommé t existera, il n'y aura aucun problème.

    Par contre, il faudra faire attention si la variable titi est créée dans fonct ou dans fonct2 dans 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
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
     
    titi& fonct()
    {
        titi t;
        t.a=12;
        t.b=14;
        return t;
    }
    titi* fonct2()
    {
        titi t;
        t.a=12;
        t.b=14;
        return &t;
    }
    titi* fonct3()
    {
        titi* t=new titi;
        t->a=12;
        t->b=14;
        return t;
    }
    int main()
    {
        titi objNOK;
        titi* ptrNOK;
        titi* OKptr
        objNOK=fonct(); /* crash (1) */
        ptrNOK=fonct2(); /* crash(2) */
        OKptr=fonct3(); /* pas crash, mais danger (3) */
        /*...*/
       return 0;
    }
    (1) et (2) La fameuse variable t créée dans et renvoyée par fonct() et fonct2() est détruite quand on quitte les fonctions, que t soit renvoyée par référence, ou par adresse

    Du coup, objNOK et prtNOK font en fait référence... à quelque chose qui n'existe plus... et qui risque d'être utilisé pour autre chose

    (3) Le fait d'allouer dynamiquement la mémoire pour t permet que cette mémoire reste "réservée" à la variable une fois que l'on a quitté la fonction... Mais...

    cette mémoire ne sera effectivement libérée que quand on le demandera explicitement (par un delete OKptr; )... et il faut donc veiller à libérer la mémoire avant de vouloir réutiliser OKptr pour autre chose, autrement, on obtiens ce que l'on appelle "une fuite mémoire" (memory leaks, en anglais):
    L'application utilise de plus en plus de mémoire, et l'ordinateur ralenti de plus en plus (avec risque de crash)
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  12. #12
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Par défaut
    Ça ne sert à rien de prendre un pointeur vers ta valeur de retour sauf si tu fais du C (c'est-à-dire que tu ne peux pas changer le comportement de la copie et de l'affectation).
    De toutes façons, techniquement, ça marche comme ça dans l'ABI quand tu retournes une structure par valeur.

Discussions similaires

  1. Tableau de généric en retour de méthodes
    Par lvr dans le forum Collection et Stream
    Réponses: 10
    Dernier message: 07/12/2009, 21h27
  2. Problème de retour de méthode (Java/Flex)
    Par Boubec dans le forum Flex
    Réponses: 2
    Dernier message: 13/11/2009, 09h52
  3. [JNI] Tableaux en paramètres et retour de méthode
    Par elamarti dans le forum Entrée/Sortie
    Réponses: 2
    Dernier message: 10/10/2008, 16h10
  4. [Objet] Conseil retour de méthode
    Par charlene44 dans le forum Delphi
    Réponses: 10
    Dernier message: 06/03/2007, 09h57
  5. reflexion et type de retour des méthodes
    Par money mark dans le forum Langage
    Réponses: 2
    Dernier message: 09/04/2006, 18h46

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