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 :

fonction de type int*


Sujet :

C++

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2009
    Messages
    90
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2009
    Messages : 90
    Points : 55
    Points
    55
    Par défaut fonction de type int*
    Bonjour à tous,
    j'aimerais savoir plus sur les fonctions du style

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int* fonction (type parm1, type parm2);

    est-ce-que c'est la meme chose que de faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int (*fonction)(type parm1, type parm2);
    ou est-ce-que c'est autre chose que j'aime pas compris

  2. #2
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 113
    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 113
    Points : 32 958
    Points
    32 958
    Billets dans le blog
    4
    Par défaut
    Bonjour,

    ça n'a strictement rien à voir.
    Dans le premier cas, tu déclares une fonction qui retourne un int* et prend 2 paramètres.
    Dans le second cas, tu déclares un pointeur sur une fonction retournant un int et qui prend 2 paramètres.
    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.

  3. #3
    Rédacteur

    Avatar de Davidbrcz
    Homme Profil pro
    Ing Supaéro - Doctorant ONERA
    Inscrit en
    Juin 2006
    Messages
    2 307
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ing Supaéro - Doctorant ONERA

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 307
    Points : 4 732
    Points
    4 732
    Par défaut
    Le premier est le prototype d'une fonction à 2 arguments renvoyant un pointeur sur un entier.

    Le second est un pointeur de fonction nommé "fonction" qui pourra être affecté a une fonction libre renvoyant un int et prenant 2 arguments.

    Edit: grillé
    "Never use brute force in fighting an exponential." (Andrei Alexandrescu)

    Mes articles dont Conseils divers sur le C++
    Une très bonne doc sur le C++ (en) Why linux is better (fr)

  4. #4
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2009
    Messages
    90
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2009
    Messages : 90
    Points : 55
    Points
    55
    Par défaut
    dans le deuxième cas j'ai compris comment faire mais dans le premier
    est ce que j'ai ce que j'aurais :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    int* fonction (type parm1, type parm2)
    {
    /*code de la fonction */
    return *quelquechose;
    }
    et dans ce cas comment ce fait l'appel de la fonction ?
    --je suis pommé --

  5. #5
    Rédacteur

    Avatar de Davidbrcz
    Homme Profil pro
    Ing Supaéro - Doctorant ONERA
    Inscrit en
    Juin 2006
    Messages
    2 307
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ing Supaéro - Doctorant ONERA

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 307
    Points : 4 732
    Points
    4 732
    Par défaut
    Comme n'importe qu'elle fonction

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    int* f(int, int)
    {
    int* r=0;
    //bla bla
    return r;
    }
     
    int* q= f(2,3);
    "Never use brute force in fighting an exponential." (Andrei Alexandrescu)

    Mes articles dont Conseils divers sur le C++
    Une très bonne doc sur le C++ (en) Why linux is better (fr)

  6. #6
    Membre expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Points : 3 156
    Points
    3 156
    Par défaut
    Citation Envoyé par pitichamo Voir le message
    dans le deuxième cas j'ai compris comment faire mais dans le premier
    J'ai comme un doute . La notion de pointeur sur un int est plus facile à maîtriser que celle de pointeur sur fonction.

    Regarde ce bout de code commenté, j'espère qu'il t'aidera à mieux comprendre :

    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
    // Déclaration d'une fonction ( à mettre dans le *.h)
    int* fonction(int parm1, int parm2);
     
    // Implémentation de la fonction ( à mettre dans le *.cpp)
    int* fonction(int parm1, int parm2)
    {
      int * resultat = new int;
      *resultat = parm1 + parm2;
      return resultat;
    }
     
    int autre_fonction(int i1, int i2)
    {
      return i1*i2;
    }
     
    int main(int argc, char* argv[])
    { 
      // Usage de la fonction qui renvoie un pointeur sur un int
      int * p1 = fonction(1,2);
      if(p1)
        delete p1;
     
      // Ceci est une variable, on déclare un pointeur de fonction
      int (*fonction_ptr)(int parm1, int parm2);
      // Usage du pointeur de fonction
      fonction_ptr = autre_fonction;
      // Appel de ce pointeur
      int resultat = (*fonction_ptr)(3,4);
     
      return 0;
    }
    Je pense que tu devrais lire un cours sur les pointeurs, ça t'aidera beaucoup.
    Find me on github

  7. #7
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Citation Envoyé par jblecanard Voir le message
    Je pense que tu devrais lire un cours sur les pointeurs, ça t'aidera beaucoup.
    +1.
    Je pense qu'avant d'aborder les pointeurs, il serait intéressant de renforcer les connaissances de base du C++.

  8. #8
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2009
    Messages
    90
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2009
    Messages : 90
    Points : 55
    Points
    55
    Par défaut
    c'est ce que j'essaie de faire mais les pointeurs y a de quoi devenir fous pour BIEN comprendre ..

  9. #9
    Membre expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Points : 3 156
    Points
    3 156
    Par défaut
    Mon non voyons, tu dis ça parce que tu ne connais pas. Les pointeurs ça fait peur aux débutants mais ça n'a rien de sorcier.
    Find me on github

  10. #10
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2009
    Messages
    90
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2009
    Messages : 90
    Points : 55
    Points
    55
    Par défaut
    Citation Envoyé par jblecanard Voir le message

    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
    // Déclaration d'une fonction ( à mettre dans le *.h)
    int* fonction(int parm1, int parm2);
     
    // Implémentation de la fonction ( à mettre dans le *.cpp)
    int* fonction(int parm1, int parm2)
    {
      int * resultat = new int;
      *resultat = parm1 + parm2;
      return resultat;
    }
     
    int autre_fonction(int i1, int i2)
    {
      return i1*i2;
    }
     
    int main(int argc, char* argv[])
    { 
      // Usage de la fonction qui renvoie un pointeur sur un int
      int * p1 = fonction(1,2);
      if(p1)
        delete p1;
     
      // Ceci est une variable, on déclare un pointeur de fonction
      int (*fonction_ptr)(int parm1, int parm2);
      // Usage du pointeur de fonction
      fonction_ptr = autre_fonction;
      // Appel de ce pointeur
      int resultat = (*fonction_ptr)(3,4);
     
      return 0;
    }
    Je pense que tu devrais lire un cours sur les pointeurs, ça t'aidera beaucoup.
    en fait une semaine après je me rend compte que y a un petit souci avec ce code; dans la fonction dont le prototype est : int* fonction(int parm1, int parm2);
    tu as initialisé int resultat en local et c'est cette meme variable qui sera retournée; dans ce cas la des que le code sort de la fonction la variable resultat n'est plus valide donc faut la mettre en globale ce qui sera mieux.


    merci beaucoup pour votre aide

  11. #11
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 113
    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 113
    Points : 32 958
    Points
    32 958
    Billets dans le blog
    4
    Par défaut
    Bonjour,

    le code est tout à fait correct.
    L'as-tu essayé pour remarquer l'erreur ?
    resultat est un pointeur auquel on alloue de la mémoire avec new dont on retourne l'adresse, à la sortie de la fonction la mémoire allouée n'est pas supprimée et l'adresse retournée est tout à fait valide et utilisable, ainsi que la valeur pointée.
    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.

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 611
    Points
    30 611
    Par défaut
    Salut,
    Citation Envoyé par pitichamo Voir le message
    en fait une semaine après je me rend compte que y a un petit souci avec ce code; dans la fonction dont le prototype est : int* fonction(int parm1, int parm2);
    tu as initialisé int resultat en local et c'est cette meme variable qui sera retournée; dans ce cas la des que le code sort de la fonction la variable resultat n'est plus valide donc faut la mettre en globale ce qui sera mieux.
    Ca va pas, non

    la duré de vie d'une valeur de retour est étendue à la portée dans laquelle la variable qui la récupère se trouve, autrement, il n'y aurait aucun intérêt à renvoyer une valeur
    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
     
    int foo(int fisrt, int second)
    {
        int i = first * second;
        return i;
    }
    int * bar(size_t size)
    {
        int * ptr = new int[size];
        return ptr;
    }
    int main()
    {
        int value;
        int myptr = 0;
        value  = foo(5, 7);
        myptr = bar(3);
        /* ... */
        delete [] myptr;
        return 0;
    }
    est donc un code tout à fait valide et correct!!!

    Il n'y aura problème que si l'on essaye de renvoyer une référence ou un pointeur sur une variable locale à la fonction:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    std::string /* const */ & concat(std::string const & first, std::string const & second)
    {
        std::string result;
        result = first + second;
        return result; // on renvoie une référence sur result, mais
    } // result est détruit ici, la référence est donc invalide
     
    int * truc( int first, int second)
    {
        int temp = first + second;
        return & temp; // on renvoye un pointeur sur temp mais
    }// temp est détruit ici : on renvoie donc un pointeur qui posera
     // problème plus tard (car l'adresse mémoire peut etre utilisée 
     // pour autre chose)
    Ceci dit, pour bien comprendre les pointeurs, il "suffit" de te dire qu'un pointeur n'est rien de plus qu'une valeur numérique un peu particulière en cela qu'elle contient en réalité l'adresse mémoire à laquelle on va trouver une variable du type précisé.

    Il faut en effet te dire que toute "chose" utilisée dans un programme se trouve à une adresse mémoire donnée (je dis chose parce que, si on se doute que c'est le cas pour une variable, il est peut etre moins évident de comprendre que c'est aussi le cas pour les fonctions )

    On peut donc demander d'obtenir l'adresse mémoire de toute chose, et cela se fait sur un pointeur

    Comme un pointeur n'est jamais qu'une valeur numérique "classique", il sera possible d'effectuer certaines opérations mathématique (essentiellement l'addition et la soustraction), mais, comme la valeur représentée est l'adresse mémoire à laquelle se trouve (ou plutôt, à laquelle est sensée se trouver) une variable du type précisé, tu te doutes que la multiplication ou la division n'auront pas de sens

    Il existe trois raisons pour vouloir utiliser un pointeur (et donc l'adresse mémoire à laquelle se trouve une variable donnée)
    1. parce que l'on souhaite prendre en charge la responsabilité de la durée de vie d'une variable
    2. parce que l'on veut utiliser l'adresse comme étant celle à laquelle se trouve le premier élément d'un ensemble contigus d'éléments de même type (tableau "C style")
    3. parce que l'on veut transmettre à une fonction un objet pour lequel les éventuelles modifications que l'on apporterait (dans la fonction) seraientrépercutées à l'objet d'origine ET que l'objet en question peut ne pas exister.

    Je pourrais disserter sur ces trois points pendant assez longtemps, mais je vais m'en tenir là pour l'instant
    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

  13. #13
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 113
    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 113
    Points : 32 958
    Points
    32 958
    Billets dans le blog
    4
    Par défaut
    Tu es d'accord pour le code suivant:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    int myFonction()
    {
      int a = 5;
      return a;
    }
    En sortie de fonction, a est perdu, mais le 5 perdure. Heureusement^^

    Pour imager grossièrement, avec des approximations, et qui me vaudront quelques coups de ceinture:
    Mais qui, je pense, est l'endroit où tu as fait une erreur.


    Imagine un pointeur comme un nombre, qui spécifie l'adresse mémoire correspondante *esquive le premier coup de ceinture*
    dans ta fonction
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    int* maFonction()
    {
      int* ptr = new int;
      *ptr = 5;
      return ptr;
    }
    Effectivement ptr a pour portée le corps de la fonction.
    En sortir de fonction, on retourne la valeur de ptr, soit une copie du nombre qui désignait l'adresse mémoire affectée. *esquive de la 2° ceinture*
    Cette copie, récupérée dans le programme principale, sera assignée à la variable qui récupère l'apelle de la fonction.
    MAIS, ptr était un pointeur sur un int, si le pointeur est perdu (l'original, mais une copie persiste par copie de valeur de retour), la mémoire allouée par le new, elle, ne l'est pas !
    Donc dans notre pointeur de retour on a un accès tout à fait normal vers cette mémoire allouée.

    Peut-être qu'un code exemple simple à exécuter pourrait t'aiguiller:
    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
    #include <iostream>
    int myFonction()
    {
      int a = 5;
      std::cout<<"myFonction::a = "<<a<<std::endl;
      std::cout<<"myFonction::&a = "<<&a<<std::endl;
      return a;
    }
    int* myPtrFonction()
    {
      int* a = new int;
      *a = 5;
      std::cout<<"myPtrFonction::a = "<<a<<std::endl;
      std::cout<<"myPtrFonction::&a = "<<&a<<std::endl;
      std::cout<<"myPtrFonction::*a = "<<*a<<std::endl;
      return a;
    }
    int main()
    {
      int* ptr;
      int val;
      std::cout<<"main::ptr = "<<ptr<<std::endl;
      std::cout<<"main::&ptr = "<<&ptr<<std::endl;
      std::cout<<"main::*ptr = mieux vaut pas tester :)"<<std::endl;
      std::cout<<"main::val = "<<val<<std::endl; // valeur aléatoire
      std::cout<<"main::&val = "<<&val<<std::endl;
     
      val = myFonction();
      ptr = myPtrFonction();
      std::cout<<"main::ptr = "<<ptr<<std::endl;
      std::cout<<"main::&ptr = "<<&ptr<<std::endl;
      std::cout<<"main::*ptr = "<<*ptr<<std::endl;
      std::cout<<"main::val = "<<val<<std::endl;
      std::cout<<"main::&val = "<<&val<<std::endl;
     
      return 1;
    }
    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.

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 611
    Points
    30 611
    Par défaut
    Essaye plutot avec une classe dans laquelle tu affiche ce qui se passe
    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
    #include <iostream>
    #include <algorithm>
    using namespace std;
    class Tester
    {
    public:
        Tester():i(10){cout<<"default constructor"<< endl;}
        Tester(Tester const & other):i(other.i)
        {
            cout<<"copy constructor"<<endl;
        }
        Tester & operator = (Tester const & other)
        {
            i=other.i;
            cout<<"affectation operator"<<endl;
        }
        ~Tester(){cout<<"destructor"<<endl;}
        int getI() const{return i;}
    private:
        int i;
    };
    Tester foo()
    {
        cout<<"foo begin"<<endl;
        Tester temp;
        cout<<"value of temp.i "<<temp.getI()<<endl;
        cout<<"foo end"<<endl;
        return temp;
    }
    int main()
    {
        cout<<"main start"<<endl;
        Tester test;
        cout<<"before foo call"<<endl;
        Tester test2 = foo();
        cout<<"after foo call"<<endl;
        return 0;
    }
    on obtient la sortie
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    main start
    default constructor
    before foo call
    foo begin
    default constructor
    foo end
    after foo call
    destructor
    destructor
    On constate que, bien que la sortie nous indique qu'il y a bien deux destructions (celle de test et celle de test2), il n'y a ni copie ni affectation (et encore moins destruction) de la variable créée dans la fonction... c'est ce qu'on appelle la copie élision, qui est active depuis déjà pas mal de temps sur la plupart des compilateurs

    Et l'on remarque, en modifiant la fonction main pour affecter le résultat de la fonction à un objet pré existant, que la sortie change à peine:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    int main()
    {
        cout<<"main start"<<endl;
        Tester test;
        cout<<"before foo call"<<endl;
        test = foo();
        cout<<"after foo call"<<endl;
        return 0;
    }
    occasionne la sortie
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    main start
    default constructor
    before foo call
    foo begin
    default constructor
    value of temp.i 10
    foo end
    affectation operator
    destructor
    after foo call
    destructor
    Tu remarqueras que l'on a un appel à l'opérateur d'affectation, mais qu'il n'y a pas de double destruction

    Seule l'implémentation de l'idiome copy and swap occasionnera bel et bien une copie et une destruction supplémentaire
    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

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

Discussions similaires

  1. Fonction ReplaceAll utilisant une variable de type int
    Par melouze dans le forum Développement de jobs
    Réponses: 4
    Dernier message: 18/09/2012, 14h19
  2. Réponses: 3
    Dernier message: 04/03/2007, 10h34
  3. Réponses: 2
    Dernier message: 27/02/2007, 19h17
  4. Fonction de type tableau
    Par Charles f dans le forum Langage
    Réponses: 5
    Dernier message: 04/08/2002, 15h04

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