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 :

string comme parametre constant dans une fonction


Sujet :

C++

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    27
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Juin 2008
    Messages : 27
    Points : 24
    Points
    24
    Par défaut string comme parametre constant dans une fonction
    je veux passer à travers une string (sans la modifier) pour extraire certaines infos
    le code suivant compile:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    bool verifyString (string theString) {
        string::iterator start = theString.begin();
        string::iterator end   = theString.end();
        while (start < end) {... start++ ...}
    par contre si j'indique que je passe une string constante dans la fonction:
    bool verifyString (const string theString) {...

    le compilateur m'indique:
    error: conversion from ‘std::basic_string<char>::const_iterator ... to non-scalar type ...

    Donc le compilateur considère que j'essaie de modifier une constante en utilisant un iterator!
    Pourquoi ?
    Est-ce mieux de faire une copie?, d'utiliser une boucle avec un size_t: for (int i = 0; i < theString.length(); i++)...
    ou de ne pas passer la string comme constante?

  2. #2
    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 965
    Points
    32 965
    Billets dans le blog
    4
    Par défaut
    Parce que tu utilises un iterator et pas un const_interator. Il te le mentionne même..
    Btw, le paramètre gagnerait à être 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.

  3. #3
    Membre régulier
    Homme Profil pro
    Cocher moderne
    Inscrit en
    Septembre 2006
    Messages
    50
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Oman

    Informations professionnelles :
    Activité : Cocher moderne

    Informations forums :
    Inscription : Septembre 2006
    Messages : 50
    Points : 118
    Points
    118
    Par défaut
    Bonjour,

    Moi-même en apprentissage, je peux peut-être aider un peu.
    Ce dont Bousk parle laconiquement, c'est de const-correctness.
    D'ailleurs, une entrée un peu détaillée ne serait pas de trop dans la FAQ, à moins que je sois passé à travers sans la voir.

    Ce qu'il faut retenir, à mon sens, c'est qu'à chaque fois (et il faut bien se discipliner) qu'une référence-pointeur-objet-attribut-whatever ne doit pas changer (est simplement lu ou copié), il FAUT le déclarer const. De même, une méthode ne changeant pas les attributs de l'objet DOIT être déclarée const.

    Une fois qu'on s'y est habitué (ou qu'on en a compris la philosophie), ça vient naturellement.

  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 965
    Points
    32 965
    Billets dans le blog
    4
    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
    Membre à l'essai
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    27
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Juin 2008
    Messages : 27
    Points : 24
    Points
    24
    Par défaut
    Il me semble que si j'indique:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    bool verifyString (string theString) {...}
    La fonction fait une copie de la variable qui peut être utilisée et modifiée localement.
    Par contre, si j'indique
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    bool verifyString (const string theString) {...}
    alors même localement je ne peux pas modifier la variable!
    Je ne vois pas en quoi mon code devient plus sécuritaire
    étant donné que la variable passée en paramètre ne changera pas de toute façon!
    ex: verifyString(uneAutreChaine); // uneAutreChaine ne vas pas pouvoir être modifiée dans la fonction.

    D'autre part si j'écris
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    bool verifyString (string& theString) {...}
    alors dans la fonction j'obtiens une référence à la variable
    et cette fois je peux modifier la variable (ex: uneAutreChaine) dans la fonction
    ce que je veux éviter.

    C'est pourquoi dans ce cas je devrais faire comme l'indique Bousk
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    bool verifyString (const string& theString) {...}
    Ainsi je ne fais pas de copie inutile d'une variable et cette variable ne peut être
    modifiée dans la fonction.

    Ai-je bien compris? Si oui, alors si je fais une copie locale comme dans mon premier exemple,
    je ne vois toujours pas pourquoi je dois utiliser un iterator constant!

  6. #6
    Membre expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2011
    Messages
    739
    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 : 739
    Points : 3 627
    Points
    3 627
    Par défaut
    Oui, tu as bien compris. Mais j'ai bien l'impression que l'erreur n'est pas dans les lignes montrées.

    Tronquer les erreurs, c'est mal ! Quelle est l'erreur complète ?

  7. #7
    Membre confirmé Avatar de Andarus
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2008
    Messages
    137
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Val de Marne (Île de France)

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

    Informations forums :
    Inscription : Novembre 2008
    Messages : 137
    Points : 455
    Points
    455
    Par défaut
    Une des règles du C++ est que l'on ne peut pas appeler de méthode non constante sur un objet constant.

    Quand tu regard la documentation de std::string::begin()
    http://www.cplusplus.com/reference/string/string/begin/
    Tu remarque deux définitions l'une constante et l'autre non constante qui se distingue par le type de retour.

    Tu dois faire appel à la méthode constante (un exemple ci-dessous) :

    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
     
    #include <iostream>
    #include <string>
     
    void showString (const std::string& str)
    {
        for ( std::string::const_iterator it=str.begin(); it!=str.end(); ++it)
        {
            std::cout << *it;
        }
        std::cout << '\n';
    }
     
     
    int main ()
    {
      std::string str ("Test string");
     
      showString(str);
     
      return 0;
    }
    Pour rendre tous çà plus simple tu peut utiliser une nouveauté du c++11 le mot-clef auto.

    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
     
    #include <iostream>
    #include <string>
     
    void showString (const std::string& str)
    {
        for ( auto it=str.begin(); it!=str.end(); ++it)
        {
            std::cout << *it;
        }
        std::cout << '\n';
    }
     
     
    int main ()
    {
      std::string str ("Test string");
     
      showString(str);
     
      return 0;
    }

    En espérant ne pas avoir dis trop de bêtise...

  8. #8
    Membre expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2011
    Messages
    739
    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 : 739
    Points : 3 627
    Points
    3 627
    Par défaut
    Encore mieux: boucle sur intervalle (for (auto & c : str) { std::cout << c; }).

  9. #9
    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 704
    Points
    2 704
    Par défaut
    Avec auto, il faut plutôt utiliser cbegin().

  10. #10
    Membre chevronné Avatar de Ehonn
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2012
    Messages
    788
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2012
    Messages : 788
    Points : 2 160
    Points
    2 160
    Par défaut
    Ce n'est pas obligatoire ici, comme str est passé par référence sur membre constant, ce sera bien la version const de .begin() qui sera appelée.
    Cependant, .cbegin() est une bonne pratique à utiliser ici aussi.

    Pour la boucle basé sur un intervalle, on peut aussi utiliser const : for (auto const & c : str) { std::cout << c; }.
    Et comme il s'agit d'un type primitif, la référence n'offre pas de gain (normalement) : for (char const c : str) { std::cout << c; } // Je n'utilise pas auto pour voir facilement qu'il s'agit d'un type primitif.

Discussions similaires

  1. Réponses: 3
    Dernier message: 19/01/2010, 14h01
  2. Parametre Range dans une fonction
    Par nox1492 dans le forum Macros et VBA Excel
    Réponses: 5
    Dernier message: 05/11/2007, 20h53
  3. [C#] Passer des contrôles comme parametre dans une fonction
    Par sara21 dans le forum Windows Forms
    Réponses: 1
    Dernier message: 20/09/2006, 13h05
  4. Fixer une constante dans une fonction générée dynamiquement ?
    Par XecTech dans le forum Général JavaScript
    Réponses: 2
    Dernier message: 07/08/2006, 20h59
  5. [débutant] mettre un parametre optionnel dans une fonction
    Par maximenet dans le forum Général JavaScript
    Réponses: 3
    Dernier message: 03/08/2006, 16h08

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