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 :

Passage par r�f�rence pour modifier une liste de string


Sujet :

C++

  1. #1
    Membre averti
    Homme Profil pro
    Administrateur de base de donn�es
    Inscrit en
    Ao�t 2016
    Messages
    11
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 39
    Localisation : Afghanistan

    Informations professionnelles :
    Activit� : Administrateur de base de donn�es

    Informations forums :
    Inscription : Ao�t 2016
    Messages : 11
    Par d�faut Passage par r�f�rence pour modifier une liste de string
    Bonjour,
    Je souhaite cr�er une liste de cha�nes de caract�res de type vector<char*> en C++ qui puisse accepter de nouvelles cha�nes issues d'une variable de type string gr�ce � une fonction. J'ai fait un code sans fonction qui marche tr�s bien :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
     
    void main()
    {
    vector<char*> listest(0); 
    string toto = "Hello";
    listest.push_back(const_cast<char*>(toto.c_str())); // J'ai dû rajouter const_cast<char*> pour passer en type char* car la méthode push_back n'acceptait pas toto.c_str() qui est de type const char*.
    cout << listest[0] << endl; 
    }
    En revanche, si je cr�e une fonction qui modifie directement listest (passage par r�f�rence), cela ne marche plus :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    void fct_test(vector<char*> *listref)
    {
    	 string toto = "Hello";
    	(*listref).push_back(const_cast<char*>(toto.c_str()));
    }
    void main()
    {
            vector<char*> listest(0);
    	fct_test(&listest);
    	cout << listest[0] << endl;
    }
    Quelqu'un saurait-il pourquoi ?
    Je me suis demand� si cela pouvait venir du passage par r�f�rence dans la fonction, mais si je fais le test suivant, cela fonctionne tr�s bien :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    void fct_test(vector<char*> *listref)
    {
    	(*listref).push_back("Hello");
    }
    void main()
    {
            vector<char*> listest(0);
    	fct_test(&listest);
    	cout << listest[0] << endl;
    }
    Le probl�me vient donc de la ligne
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    (*listref).push_back(const_cast<char*>(toto.c_str()))
    dans la fonction, mais cette ligne fonctionne tr�s bien dans le main(), donc je ne comprends pas.

    Merci de votre aide,
    Andrew

  2. #2
    Membre Expert
    Homme Profil pro
    Ing�nieur d�veloppement logiciels
    Inscrit en
    Juin 2011
    Messages
    760
    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 : 760
    Par d�faut
    Ces codes ont au minimum 3 probl�mes:

    - Un usage abusif de pointeur l� le bon sens voudrait une r�f�rence.
    - Vouloir manipuler des cha�nes de caract�res avec char*. Surtout quand l'origine est un std::string.
    - Caster le retour de c_str().

    Si tu veux comprendre ton erreur, relis la doc sur std::string::c_str(), c'est une valeur temporaire est contr�l� par std::string. Quand std::string est modifi�, ce pointeur ne doit plus �tre utilis�.
    La destruction d'un std::string est un changement d'�tat.

  3. #3
    Membre averti
    Homme Profil pro
    Administrateur de base de donn�es
    Inscrit en
    Ao�t 2016
    Messages
    11
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 39
    Localisation : Afghanistan

    Informations professionnelles :
    Activit� : Administrateur de base de donn�es

    Informations forums :
    Inscription : Ao�t 2016
    Messages : 11
    Par d�faut
    Merci pour ta r�ponse.

    - Un usage abusif de pointeur l� le bon sens voudrait une r�f�rence
    Je pensais que pointeur et r�f�rence voulaient dire la m�me chose. Dans le cas pr�sent, mon bon sens me disait de passer des adresses en param�tres d'une fonction plut�t que la variable. Et de ce que j'ai lu, un pointeur est une adresse. Je vais revoir ce point.

    - Vouloir manipuler des cha�nes de caract�res avec char*. Surtout quand l'origine est un std::string
    En amont, je re�ois un std::string, cela je ne peux rien y changer. En revanche, pour stocker les cha�nes de caract�res, je pr�f�rais utiliser un tableau de char* plut�t qu'un tableau de string car je pensais que c'�tait moins couteux en m�moire. Qu'en penses-tu ?

    Concernant std::string::c_str(), j'ai lu qu'il s'agissait d'un pointeur vers la cha�ne de caract�res correspondant au string d�clar� avec le caract�re nul � la fin. Tu me dis qu'il ne faut plus utiliser ce pointeur quand std::string est modifi�. Dans mon cas, puisqu'on est dans une fonction, je pense qu'� la fin de son ex�cution, le string toto est d�truit. Mais j'acc�de au pointeur avant la destruction du string toto donc je ne comprends pas ?

  4. #4
    Membre Expert
    Avatar de Pyramidev
    Homme Profil pro
    Tech Lead
    Inscrit en
    Avril 2016
    Messages
    1 513
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyr�n�es)

    Informations professionnelles :
    Activit� : Tech Lead

    Informations forums :
    Inscription : Avril 2016
    Messages : 1 513
    Par d�faut
    Citation Envoy� par jamesandrew Voir le message
    En revanche, pour stocker les cha�nes de caract�res, je pr�f�rais utiliser un tableau de char* plut�t qu'un tableau de string car je pensais que c'�tait moins couteux en m�moire.
    Dans ce cas, au moins, remplace vector<char*> par vector<const char*> et supprime les const_cast<char*>.

    char*, et donc aussi vector<char*>, permet de modifier le contenu d'une cha�ne.
    Mais si le programme a stock� la cha�ne dans une zone m�moire accessible uniquement en lecture, alors tenter de la modifier fera probablement crasher le programme.

    H�las, en C++98, les constantes litt�rales comme "Hello" sont convertibles en char*, par r�trocompatibilit� avec le C. Mais cette anomalie est corrig�e en C++11. Ainsi, le code suivant ne compilera plus en C++11 :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    void fct_test(vector<char*> *listref)
    {
    	(*listref).push_back("Hello");
    }
    Citation Envoy� par jamesandrew Voir le message
    Dans mon cas, puisqu'on est dans une fonction, je pense qu'� la fin de son ex�cution, le string toto est d�truit. Mais j'acc�de au pointeur avant la destruction du string toto donc je ne comprends pas ?
    Lors de la destruction de toto, la m�moire contenant la cha�ne de caract�res point�e par toto.c_str() est lib�r�e.
    Le fait d'avoir copi� quelque part ailleurs l'adresse vers cette cha�ne de caract�res n'emp�che pas cette lib�ration.

    Si tu veux persister � utiliser std::vector<const char*> :
    • Tu peux faire push_back sur une constante litt�rale, par exemple myVector.push_back("Hello"). Ce n'est pas dangereux car ces cha�nes sont allou�es pour toute la dur�e de l'ex�cution du programme.
    • Si tu fais myVector.push_back(objetStdString.c_str()), �a va �tre sportif. Je conseille alors que objetStdString soit de type const std::string. Comme �a, tu n'auras plus � te soucier que objetStdString ne soit pas modifi� en cours de vie, mais "seulement" qu'il ne soit pas d�truit trop t�t.


    Cependant, � moins que la performance soit un crit�re crucial de ton programme, je conseille vivement de pr�f�rer std::vector<std::string>. La cha�ne sera copi�e � chaque insertion* mais, au moins, il n'y aura plus de risque de pointer vers une cha�ne d�truite.

    * : Sauf si l'impl�mentation de std::string utilise le Copy On Write, mais c'est une autre histoire.

  5. #5
    Membre Expert
    Homme Profil pro
    Ing�nieur d�veloppement logiciels
    Inscrit en
    Juin 2011
    Messages
    760
    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 : 760
    Par d�faut
    Citation Envoy� par Pyramidev Voir le message
    * : Sauf si l'impl�mentation de std::string utilise le Copy On Write, mais c'est une autre histoire.
    Ou que le constructeur de d�placement soit utilis�. Surtout que si je comprends bien, la cha�ne existe toujours et va �tre stock�e dans le vecteur quoi qu'il arrive. Il y a tout int�r�t � utiliser un vecteur de std::string et std::move dans cette situation.

  6. #6
    Membre averti
    Homme Profil pro
    Administrateur de base de donn�es
    Inscrit en
    Ao�t 2016
    Messages
    11
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 39
    Localisation : Afghanistan

    Informations professionnelles :
    Activit� : Administrateur de base de donn�es

    Informations forums :
    Inscription : Ao�t 2016
    Messages : 11
    Par d�faut
    C'est bon j'ai compris mes erreurs sur les pointeurs, j�utilise maintenant un vecteur de string et �a marche tr�s bien. Merci beaucoup

+ R�pondre � la discussion
Cette discussion est r�solue.

Discussions similaires

  1. Probl�me pour parcourir une liste de String
    Par Invit� dans le forum D�buter avec Java
    R�ponses: 13
    Dernier message: 21/07/2010, 18h31
  2. R�ponses: 4
    Dernier message: 26/12/2009, 20h48
  3. R�ponses: 8
    Dernier message: 03/12/2006, 17h46
  4. passage par r�f�rence d'un buffer de type String
    Par youp_db dans le forum Langage
    R�ponses: 2
    Dernier message: 11/10/2006, 10h51
  5. R�ponses: 4
    Dernier message: 26/12/2005, 17h01

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