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 :

Question argument d'une fonction de type string


Sujet :

C++

  1. #1
    Membre confirmé
    Inscrit en
    Juin 2002
    Messages
    59
    Détails du profil
    Informations forums :
    Inscription : Juin 2002
    Messages : 59
    Par défaut Question argument d'une fonction de type string
    Bonjour,

    Juste une question
    J'ai beacoup lu des tutorials sur les strings
    et j'arrive toujours pas à comprendre pourquoi

    quand on met un argument de type string on doit toujours faire "const string& nom_var"

    ex :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    string fonction_name(const string& variable_name)
    {
       //Code here
    }


    pourquoi ne pas faire tout simplement commme suit
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    string fonction_name(string variable_name)
    {
       //Code here
    }
    ou aussi
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    string fonction_name(string& variable_name)
    {
       //Code here
    }

  2. #2
    Expert confirmé
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 296
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 296
    Par défaut
    Parce que copier coute cher quand un objet est plus gros qu'un int.
    Et parce qu'un réaliser une allocation et une libération (ce qui se passe en interne quand on copie des strings) coute encore plus cher.
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  3. #3
    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 met le mot clef const pour indiquer que, dans la fonction, il n'est pas autorisé de modifier la variable.

    On passe par référence pour éviter de perdre du temps à copier, c'est tout ce qu'il y a à comprendre, faut pas chercher plus loin.

    Quand tu dis "on doit toujours faire", c'est faux, parfois on veut pouvoir mettre à jour la variable passée en argument, sans la passer par le return. On ne met pas de const dans ce cas.

    Parfois on préférera carrément en faire une copie en la passant par valeur pour pouvoir travailler dessus sans risque.

  4. #4
    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,

    Il y a une dernière raison, qui justifie la constance de la référence:

    La norme interdit de créer des références anonymes non constantes.

    C'est à dire que, si tu veux appeler ta fonction sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    string  str=function_name("salut koala");
    /* ce qui aurait pu être séparé en */
    string str;
    /*...*/
    str=function_name("salut koala");
    la version prenant une chaine par valeur aura l'inconvénient de provoquer la copie de la chaine, et la version prenant une référence non constante ne sera pas admise.

    Seule la version prenant une référence constante pourra fonctionner en évitant les deux écueils
    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

  5. #5
    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
    Bien vu, mais c'est bien dommage.

  6. #6
    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
    non, c'est normal:

    une référence peut servir d'argument in/out...

    Or, si tu laisse une référence non constante, la fonction qui la reçoit en argument est susceptible de modifier cet argument.

    Et, pourtant, si la fonction est appelée sous la forme présentée lors de mon intervention précédente, il sera impossible de modifier cet argument, étant donné que quel que soit le type de l'argument, il sera créé de manière temporaire, et le langage n'a aucun moyen de faire la différence, s'il vient à accepter une référence non constante.

    Dés lors, le fait de forcer les référence anonymes à être constantes permet de prendre les différents cas en considération:

    Si l'argument est à considérer comme in/out, il ne doit pas être constant, mais il faut qu'une variable du bon type existe avant l'appel de la fonction, alors que s'il doit pouvoir être créé de manière anonyme, il n'a aucune raison d'être volatile, ni de servir d'argument in/out
    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

  7. #7
    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
    Ben si justement, il pourrait y en avoir des raisons. Je me suis déjà frotté au cas, c'est pour ça que je dis ça aujourd'hui. Mais pas grave je vivrais avec.

    Par exemple il m'aurait bien été utile d'avoir une référence non constante pour un retourner une variable afin d'implémenter une nouvelle fonctionnalité (le return était déjà pris), sans obliger l'utilisateur de la fonction à utiliser ce retour (variable par défaut).

    A priori je ne vois rien qui empêcherait le compilateur de retomber sur ses pattes si la variable par défaut est utilisée : il créé un bête temporaire avant l'appel, il l'utilise, le modifie à souhait, et le détruit à la fin de la fonction.

    Ben non, je suis forcé de passer soit par un pointeur [et aller, c'est parti pour une longue série de if (pointeur) pointeur->truc(); très joli...] ou alors une fonction wrapper qui effectivement créé le temporaire avant l'appel, le job suposé du compilo quoi, lazy b*st*rd...

    quoi je l'ai mauvaise ?? effectivement elle a eu du mal à passer celle-là.

  8. #8
    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
    Citation Envoyé par NiamorH Voir le message
    Ben si justement, il pourrait y en avoir des raisons. Je me suis déjà frotté au cas, c'est pour ça que je dis ça aujourd'hui. Mais pas grave je vivrais avec.

    Par exemple il m'aurait bien été utile d'avoir une référence non constante pour un retourner une variable afin d'implémenter une nouvelle fonctionnalité (le return était déjà pris), sans obliger l'utilisateur de la fonction à utiliser ce retour (variable par défaut).
    Voyons... réfléchi un peu...

    Comment voudrais tu utiliser une valeur modifiée de la chaine "salut koala" lors d'un appel du genre de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int i = mafonct("salut koala");

    quel nom donnerais tu à la variable devant recevoir la valeur modifiée, après appel de la fonction

    Si tu veux disposer de la valeur modifiée, tu n'as pas le choix, il te faut une variable légalement déclarée au sein de la fonction appelante pour y accéder.

    Et donc, le code utilisable devient
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    std::string str="salut koala";
    int i = mafonct(str);
    /* possibilité d'utiliser str qui sera modifié */
    pour autant que tu aie passé str en tant que référence non constante (ce qui est autorisé )
    A priori je ne vois rien qui empêcherait le compilateur de retomber sur ses pattes si la variable par défaut est utilisée : il créé un bête temporaire avant l'appel, il l'utilise, le modifie à souhait, et le détruit à la fin de la fonction.
    Ce n'est pas tant le fait que le compilateur puisse créer une variable temporaire, c'est surtout qu'il faut que tu puisse éventuellement utiliser cette variable, en n'ayant aucune idée du nom que le compilateur peut lui avoir donné...

    Au sein de la fonction appelée, tu dispose du nom de l'argument fourni, mais, au sein de la fonction appelante, tu ne dispose de toutes manières d'aucun moyen de récupérer cette valeur modifiée (cf plus haut )

    Il n'y a donc a priori aucune raison pour autoriser la modification d'une référence anonyme (à comprendre: d'une variable créée sur base d'une valeur n'étant pas une variable dans la fonction appelante)
    Ben non, je suis forcé de passer soit par un pointeur [et aller, c'est parti pour une longue série de if (pointeur) pointeur->truc(); très joli...] ou alors une fonction wrapper qui effectivement créé le temporaire avant l'appel, le job suposé du compilo quoi, lazy b*st*rd...
    Non, tu es obligé de passer par une variable correctement déclarée dans la fonction appelante, et par une référence - éventuellement non constante - sur cette variable dans la fonction appelée.

    L'utilisation d'une référence non constante, quand elle a lieu dans le contexte d'une variable légalement déclarée au sein de la fonction appelante ne pose absolument aucun problème, et permet d'avoir un argument in/out...

    Ce qui pose problème, c'est de vouloir utiliser comme argument in/out une valeur qui n'est pas une variable légalement déclarée dans la fonction appelante.

    Encore une fois, relis le lignes ci-dessus pour comprendre pourquoi il serait de toutes façons inutile de le permettre
    quoi je l'ai mauvaise ?? effectivement elle a eu du mal à passer celle-là.
    En fait, j'ai l'impression que tu as simplement mal compris le priincipe d'une "référence anonyme"

    Les quelques lignes qui précèdent t'auront, je l'espère, permis de comprendre de quoi il s'agit réellement, et auront sans doute pour effet de fluidifier le passage

    Quand on parle de référence anonyme, il s'agit en réalité d'une "référence sur une variable anonyme (qui n'a pas de nom légalement déclaré)"
    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

  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
    Citation Envoyé par koala01 Voir le message
    Voyons... réfléchi un peu...

    Comment voudrais tu utiliser une valeur modifiée de la chaine "salut koala" lors d'un appel du genre de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int i = mafonct("salut koala");
    C'est au compilateur de me donner une jolie error pour ce cas particulier où j'écrirais de la m****, il en est capable.


    Citation Envoyé par koala01 Voir le message
    Si tu veux disposer de la valeur modifiée, tu n'as pas le choix, il te faut une variable légalement déclarée au sein de la fonction appelante pour y accéder.

    ...

    Ce n'est pas tant le fait que le compilateur puisse créer une variable temporaire, c'est surtout qu'il faut que tu puisse éventuellement utiliser cette variable,

    ...

    au sein de la fonction appelante, tu ne dispose de toutes manières d'aucun moyen de récupérer cette valeur modifiée (cf plus haut )

    ...

    Il n'y a donc a priori aucune raison pour autoriser la modification d'une référence anonyme
    Citation Envoyé par Niamorh
    A priori je ne vois rien qui empêcherait le compilateur de retomber sur ses pattes si la variable par défaut est utilisée : il créé un bête temporaire avant l'appel, il l'utilise, le modifie à souhait, et le détruit à la fin de la fonction.
    Tu n'a visiblement pas saisi l'intérêt qui existe bel et bien :

    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
    int fonction( int ancien = 1, NouvelObjet & nouvelle fonctionnalité = NouvelObjet() );
     
    void
    Anciennefonctionquisefichetotalementdelanouvellefonctionnalite()
    {
      // Aucune modification sur le fichier
      int resultat = fonction( 7 );
    }
     
    void
    Nouvellefonctionquiaimeraitbienutiliserlanouvellefonctionnalite()
    {
      // Ben la j'utilise une variable puisque je m'en sert après
      NouvelObjet objt;
      int resultat = fonction( 7, objt );
      if ( objt.EstDansEtat() == truc )
        // faire d' autres supers trucs;
    }
    C'est ça l'intérêt rien de plus. Et je ne vois aucune contrainte technique énorme pour qu'elle puisse être implémentée.

    en n'ayant aucune idée du nom que le compilateur peut lui avoir donné...
    Si par cette phrase tu te demandais comment s'en servir, on s'en balance vu que c'est pas le but, si tu te demandais si il n'y allais pas y avoir de conflit de noms avec des variables locales, le compilateur peut utiliser une variable avec un nom commençant par underscore, elle lui sont réservées.

    Encore une fois, relis le lignes ci-dessus pour comprendre pourquoi il serait de toutes façons inutile de le permettre
    Je suis pas du tout d'accord, relis les lignes dessus pour comprendre pourquoi il seriat utilise de le permettre.

    En fait, j'ai l'impression que tu as simplement mal compris le priincipe d'une "référence anonyme"
    C'est possible, une variable par défaut est-elle considérée comme anonyme ? Parce que c'est cela dont je parle. Et qu'il est interdit en tant que reference non constante.

  10. #10
    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
    non, ce qui est interdit c'est une référence sur une variable anonyme non constante...

    La notion d'argument par défaut est à comprendre dans le sens de "en dehors de toute indication contraire de la part de l'utilisateur" et n'est clairement pas considéré, au sein de la fonction qui l'utilise, comme une variable anonyme... la preuve: l'argument a un nom

    Tu peux très bien fournir une valeur par défaut sur une référence non constante

    Mais, de là à récupérer un objet créé (pourquoi pas par défaut) de manière temporaire à une fonction et - éventuellement - modifié au sein de cette fonction dans la fonction qui l'appelle, explique moi comment tu voudrais t'y prendre
    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

  11. #11
    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
    Citation Envoyé par koala01 Voir le message
    Mais, de là à récupérer un objet créé (pourquoi pas par défaut) de manière temporaire à une fonction et - éventuellement - modifié au sein de cette fonction dans la fonction qui l'appelle, explique moi comment tu voudrais t'y prendre
    J'abandonne, j'ai déjà expliqué que ce n'était pas mon but.

    Tu peux très bien fournir une valeur par défaut sur une référence non constante.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    class B {};
     
    class A
    {
      void func( B & b = B() );
    };
    Comeau C/C++ 4.3.9 (Mar 27 2007 17:24:47) for ONLINE_EVALUATION_BETA1
    Copyright 1988-2007 Comeau Computing. All rights reserved.
    MODE:strict errors C++ C++0x_extensions

    "ComeauTest.c", line 5: error: initial value of reference to non-const must be an lvalue
    void func( B & b = B() );

    1 error detected in the compilation of "ComeauTest.c".

  12. #12
    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
    Citation Envoyé par NiamorH Voir le message
    J'abandonne, j'ai déjà expliqué que ce n'était pas mon but.
    Au temps pour moi... je viens de "percuter" sur ton but réel...

    Et, vérification faite, effectivement un argument passé comme référence ayant une valeur par défaut doit être fournis sous la forme d'une référence constante (re )

    Mais, ceci dit, l'argument peut très bien rester valable au sein de la fonction appelée:

    Normalement, quand tu donne un objet par défaut à un argument, c'est que tu estime que "dans la plupart des cas", l'objet par défaut permettra d'arriver au but que tu t'es fixé, et qu'il est donc "inutile" de forcer à fournir toujours cet objet

    Or, si tu dois commencer par modifier quelque chose dans cet objet avant de pouvoir l'utiliser (ou en cours d'utilisation):
    1. cela indique sans doute que tu n'a pas réfléchi assez aux informations que devait contenir ton objet par défaut
    2. toutes les modifications que tu pourrais apporter seront de toutes manières perdues en sortir de fonction... dés lors, on peut se poser la question de leur utilité réelle
    3. tu romps avec le sacrosaint principe de la délégation des tâches: ta fonction reçoit une responsabilité à laquelle elle ne devrait pas prétendre


    Dés lors, cela ne me gène absolument pas que l'objet fournis par défaut soit constant dans ce cas de figure, et cela devrait peut être t'inciter à réfléchir d'avantage aux informations contenues par l'objet par défaut, voire, à factoriser d'avantage ton code ... ou, pourquoi pas, à envisager plutôt la surcharge de la fonction, de manière à pouvoir utiliser l'objet "par défaut" dans l'une des fonctions et l'objet reçu en argument dans l'autre
    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
    screetch
    Invité(e)
    Par défaut
    d'ou la construction typiquement C++ienne

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::vector().swap(variable);
    car

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    variable.swap(std::vector());
    ne compile pas. (je crois que Visual C++ l'accepte cependant)

  14. #14
    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
    Citation Envoyé par koala01 Voir le message
    • toutes les modifications que tu pourrais apporter seront de toutes manières perdues en sortir de fonction... dés lors, on peut se poser la question de leur utilité réelle
    Tout à fait d'acord pour dire que les données ne sont pas utiles tout le temps. D'où l'intérêt d'un argument par défaut.

    Comment t'expliquer... Parfois, tu n'est pas intéressé par le code de retour de certaines fonctions ? Pourtant la fonction s'éforce à chaque fois de te retourner un beau code cohérent. Ben là c'est pareil. Libre à l'utilisateur de ne pas sans servir.

    Citation Envoyé par koala01 Voir le message
    • tu romps avec le sacrosaint principe de la délégation des tâches: ta fonction reçoit une responsabilité à laquelle elle ne devrait pas prétendre
    D'accord aussi. Mais tu laisses un aspect de coté :

    Imagine que tu implémente un compilateur (woah le taf).

    Quelle implémentation choisirais-tu :

    - Scanner d'abord les warnings (1ere boucle)
    - Puis compiler (2eme boucle)

    ou

    - Compiler jusqu'à trouver des erreurs en stocquant au fur et à mesure les erreurs (1 seule boucle)

    ?

    C'est exactement ce que je fais : un traitement avec un retour d'erreurs sous forme de string (utilisé ou non pour affichage ou autre après appel)

    ou, pourquoi pas, à envisager plutôt la surcharge de la fonction, de manière à pouvoir utiliser l'objet "par défaut" dans l'une des fonctions et l'objet reçu en argument dans l'autre
    C'est la solution du wrapper de fonction que j'ai déjà évoqué. C'est plus joli qu'une solution à base de pointeur, mais (je me répète) c'est vraiment dommage que la ref non constante ne soit pas compatible avec les argument par défaut car c'est l'écriture la plus simple pour faire cela, tout en restant logique et implémentable par les compilos.

  15. #15
    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
    Citation Envoyé par NiamorH Voir le message
    Tout à fait d'acord pour dire que les données ne sont pas utiles tout le temps. D'où l'intérêt d'un argument par défaut.

    Comment t'expliquer... Parfois, tu n'est pas intéressé par le code de retour de certaines fonctions ? Pourtant la fonction s'éforce à chaque fois de te retourner un beau code cohérent. Ben là c'est pareil. Libre à l'utilisateur de ne pas sans servir.
    Il ne faut pas confondre le but d'un retour de fonction avec celui d'un argument.

    Le but du retour de fonction est... de fournir le résultat du traitement au sein de la fonction.

    Celui d'un argument est... de fournir les informations dont la fonction a besoin pour travailler mais qu'elle est incapable de trouver par elle-même

    Quand tu fournis un argument par défaut, cela revient seulement à dire à l'utilisateur de la fonction (à comprendre ici: celui qui décidera de l'invoquer dans son code )que
    Normalement, vous devriez fournir un argument de <tel type>, mais, comme j'ai remarqué qu'une valeur peut être utiliser dans une majorité de cas - et que je suis un mec décidément trop bon - j'ai décidé d'être gentil et de vous faciliter le travail, et vous n'êtes donc pas obligé fournir l'argument si la valeur vous convient (en respectant les limitations d'usage ).
    Mais comme le but d'un argument est - à la base - de fournir à la fonction les informations nécessaires pour effectuer son travail en toute quiétude, la fonction ne devrait - a priori - jamais avoir la responsabilité de modifier une donnée au sein de l'argument.

    Comme souvent, on se rend compte que le comportement "par défaut" (ici, la possiblité de faire subsister les modification apportée à un argument en dehors de la fonction) ne correspond qu'à une exception... qui n'entre pas dans le cadre "stricto senso" d'une méthode d'objet ou d'une fonction. (remarque que Java, par exemple, prend le problème dans l'autre sens, avec d'autres implications: pour lui, tout objet est toujours constant... et ce n'est pas forcément mieux :p)

    Comme la modification de l'argument reçu par l'argument n'a - a priori - rien à faire dans une fonction, et que, en plus, en ce qui concerne ceux qui ont des valeurs par défaut, il devient impossible de jouir de ces valeurs en dehors de la fonction dans laquelle ils sont utilisés, j'estime parfaitement cohérent de ne pas autoriser les références anonymes non constantes.

    Ceci dit, Je ne prétend pas que les décisions prises par le comité de standardisation soient les meilleures sur le sujet... je dis simplement que ce sont - de mon point de vue strictement personnel - les plus cohérentes par rapport aux autres, et par rapport à ma définition (peut être un peu trop) personnelle (à ton gout ) d'un argument

    D'accord aussi. Mais tu laisses un aspect de coté :

    Imagine que tu implémente un compilateur (woah le taf).

    Quelle implémentation choisirais-tu :

    - Scanner d'abord les warnings (1ere boucle)
    - Puis compiler (2eme boucle)

    ou

    - Compiler jusqu'à trouver des erreurs en stocquant au fur et à mesure les erreurs (1 seule boucle)

    ?

    C'est exactement ce que je fais : un traitement avec un retour d'erreurs sous forme de string (utilisé ou non pour affichage ou autre après appel)

    C'est la solution du wrapper de fonction que j'ai déjà évoqué. C'est plus joli qu'une solution à base de pointeur, mais (je me répète) c'est vraiment dommage que la ref non constante ne soit pas compatible avec les argument par défaut car c'est l'écriture la plus simple pour faire cela, tout en restant logique et implémentable par les compilos.
    Même dans le cadre de l'implémentation d'un compilateur... la fonction est quand même destinée à être appelée, et, s'il y a des arguments à lui fournir de manière à lui permettre de travailler, on souhaitera sans doute récupérer, à un moment ou un autre les arguments volatiles qu'on lui aura passé

    Dés lors, on en revient toujours au même point: il faut une variable existante pour les récupérer en dehors de la fonction (je sais, ce n'est pas ce dont tu parle, mais étant donné que c'est le but final de tels arguments... ) et que l'on passe donc du problème de référence sur variable anonyme à un problème tout à fait classique de devoir récupérer plus d'un résultat lors de l'appel d'une fonction
    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

  16. #16
    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
    Citation Envoyé par koala01 Voir le message
    Celui d'un argument est... de fournir les informations dont la fonction a besoin pour travailler mais qu'elle est incapable de trouver par elle-même
    Absolument pas d'accord.
    Il existe des paramètres en entrée seule, en sortie seule, et en entrée/sortie.
    Un lien au hasard : http://www.jaylelillois.info/index.p...chap3&desc=iut

    Mais comme le but d'un argument est - à la base - de fournir à la fonction les informations nécessaires pour effectuer son travail en toute quiétude, la fonction ne devrait - a priori - jamais avoir la responsabilité de modifier une donnée au sein de l'argument.
    De fait, pas d'accord. Ce serait le cas si le paramètre était const seulement. Un paramètre non const peut être modifié en récupéré en sortie... C'est quand même dingue de dire ça.

    Comme souvent, on se rend compte que le comportement "par défaut" (ici, la possiblité de faire subsister les modification apportée à un argument en dehors de la fonction) ne correspond qu'à une exception... qui n'entre pas dans le cadre "stricto senso" d'une méthode d'objet ou d'une fonction. (remarque que Java, par exemple, prend le problème dans l'autre sens, avec d'autres implications: pour lui, tout objet est toujours constant... et ce n'est pas forcément mieux :p)

    Comme la modification de l'argument reçu par l'argument n'a - a priori - rien à faire dans une fonction, et que, en plus, en ce qui concerne ceux qui ont des valeurs par défaut, il devient impossible de jouir de ces valeurs en dehors de la fonction dans laquelle ils sont utilisés, j'estime parfaitement cohérent de ne pas autoriser les références anonymes non constantes.
    Pour moi, ça n'a vraiment aucun sens ce que tu dis. Tu pars d'une règle avec laquelle je ne suis pas d'accord. Voir plus haut.


    Même dans le cadre de l'implémentation d'un compilateur... la fonction est quand même destinée à être appelée, et, s'il y a des arguments à lui fournir de manière à lui permettre de travailler, on souhaitera sans doute récupérer, à un moment ou un autre les arguments volatiles qu'on lui aura passé
    Les arguments volatiles ? Fais attention, les termes que tu emploies pour faire de jolies phrases ont un sens en C++, ça devient parfois étrange de te lire et pas toujours facile à comprendre.
    Pareil : essaye d'être précis lorsque tu parles d'argument/paramètre. C'est juste histoire de se comprendre plus facilement.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    // a est un paramètre
    void f( int a );
     
    int main()
    {
      // 9 est un argument
      f( 9 );
    }

    l'on passe donc du problème de référence sur variable anonyme à un problème tout à fait classique de devoir récupérer plus d'un résultat lors de l'appel d'une fonction
    Oui !!!!
    C'est ça que j'ai dis bien plus haut : mon retour est déjà utilisé !! Sinon je m'en serais bien évidement servi !

  17. #17
    Membre chevronné
    Profil pro
    Inscrit en
    Février 2008
    Messages
    439
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 439
    Par défaut
    Citation Envoyé par NiamorH Voir le message
    Tu n'a visiblement pas saisi l'intérêt qui existe bel et bien :

    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
    int fonction( int ancien = 1, NouvelObjet & nouvelle fonctionnalité = NouvelObjet() );
     
    void
    Anciennefonctionquisefichetotalementdelanouvellefonctionnalite()
    {
      // Aucune modification sur le fichier
      int resultat = fonction( 7 );
    }
     
    void
    Nouvellefonctionquiaimeraitbienutiliserlanouvellefonctionnalite()
    {
      // Ben la j'utilise une variable puisque je m'en sert après
      NouvelObjet objt;
      int resultat = fonction( 7, objt );
      if ( objt.EstDansEtat() == truc )
        // faire d' autres supers trucs;
    }
    En l'espèce, il suffit de faire une fonction de délégation (forwarding) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    int fonction( int ancien, NouvelObjet & nouvelle fonctionnalité);
     
    inline int fonction( int ancien = 1) {
    	NouvelObjet tmp;
    	fonction (ancien, tmp);
    }
    Dans ce cas précis, je ne vois pas vraiment l'intérêt de lier une référence à une rvalue.

    Et puis, les arguments par défauts, beurk.

  18. #18
    Membre chevronné
    Profil pro
    Inscrit en
    Février 2008
    Messages
    439
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 439
    Par défaut Acrobatie
    Citation Envoyé par NiamorH Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    class B {};
     
    class A
    {
      void func( B & b = B() );
    };
    La plupart du temps, y'a des trucs faisables :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    class B {};
     
    class A
    {
      void func( B & b = (B()=B()) );
    };
    mais bon.

  19. #19
    Membre chevronné
    Profil pro
    Inscrit en
    Février 2008
    Messages
    439
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 439
    Par défaut Question de vocabulaire
    Citation Envoyé par koala01 Voir le message
    du problème de référence sur variable anonyme
    l'interdiction de lier une référence non-constante à une rvalue

  20. #20
    Membre expérimenté
    Profil pro
    Inscrit en
    Août 2007
    Messages
    190
    Détails du profil
    Informations personnelles :
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations forums :
    Inscription : Août 2007
    Messages : 190
    Par défaut
    @corrector :
    Pourrais tu expliquer pourquoi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    class B {};
     
    class A
    {
      void func( B & b = (B()=B()) );
    };
    fonctionne

    D'avance merci

Discussions similaires

  1. Réponses: 5
    Dernier message: 14/07/2010, 10h34
  2. Réponses: 9
    Dernier message: 10/05/2010, 21h35
  3. Réponses: 11
    Dernier message: 18/02/2007, 15h37
  4. Detecter le type d'un argument d'une fonction
    Par flipper203 dans le forum C++
    Réponses: 31
    Dernier message: 07/07/2006, 22h53
  5. passer FILE* en argument d une fonction
    Par Monsieur_Manu dans le forum C
    Réponses: 9
    Dernier message: 10/04/2003, 17h56

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