STL: Problème stockage dans un container multimap

Résolu
elnino67 Messages postés 3 Date d'inscription jeudi 22 mai 2008 Statut Membre Dernière intervention 29 mai 2008 - 22 mai 2008 à 21:24
luhtor Messages postés 2023 Date d'inscription mardi 24 septembre 2002 Statut Membre Dernière intervention 28 juillet 2008 - 23 mai 2008 à 18:24
Bonsoir,

Nous utilisons un programme ayant recours à une multimap utilisant:

[code] multimap<string, class Client> m;[\CODE]

en clé: le champ nom d'une classe Client, et en objet: Client.

<!-- BEGIN TEMPLATE: bbcode_code -->

Code :
 
class Client
{private:
int m_id;
string m_nom;
string m_prenom;
Adresse *m_adress;

public:
void afficher(std::ostream &out);
Client();
~Client();
string getnom();
string getprenom();
Adresse* getadress();
void setnom(string);
void setprenom(string);
void setadress(Adresse*);
Client nouveauclient();
Client &operator=(const Client &);
//acheter();//avis(); };

<!-- END TEMPLATE: bbcode_code -->Nous avons crée une fonction devant permettre la création d'un nouveau client via la saisie de l'utilisateur.

<!-- BEGIN TEMPLATE: bbcode_code -->

Code :
Client Client :: nouveauclient(){
Client nouveau;
int num,cp;
char nom2[200],prenom2[200],rue2[400],ville2[200];
string rue,ville;



 
cout << "veuillez saisir votre nom : " <<endl;
fflush(stdin);
gets(nom2);
 
 
cout << "veuillez saisir votre prenom : " <<endl;
fflush(stdin);
gets(prenom2);

cout << "veuillez saisir votre numero d'adresse : " <<endl;
cin>>num;

cout<< "Veuillez saisir votre rue : "<<endl;
fflush(stdin);
gets(rue2);

cout << "Veuillez saisir votre ville : "<<endl;
fflush(stdin);
gets(ville2);

cout << "veuillez saisir votre code postal : " <<endl;
cin>>cp;

nouveau.setnom(nom2);
nouveau.setprenom(prenom2);
rue=rue2;
ville=ville2;
 

nouveau.getadress()->setnum(num);
nouveau.getadress()->setville(ville);
nouveau.getadress()->setrue(rue);
nouveau.getadress()->setcp(cp);

 
return nouveau;
}
 

<!-- END TEMPLATE: bbcode_code -->Le retour de cette fonction est affecté dans le main à une variable de type Client:

<!-- BEGIN TEMPLATE: bbcode_code -->

Code :
clien=clien.nouveauclient();

<!-- END TEMPLATE: bbcode_code -->Ce nouveau client nous essayons de l'insérer dans la multimap de la manière suivante :

<!-- BEGIN TEMPLATE: bbcode_code -->

Code :
 
m.insert(make_pair(clien.getnom(),clien));
 

<!-- END TEMPLATE: bbcode_code -->Mais une fois cette insertion effectué, l'affichage du contenu de la multimap fais planter le programme.

Le seul moyen de réussir à afficher le contenu de la multimap est de changer l'objet en l'établissant comme pointeur :

<!-- BEGIN TEMPLATE: bbcode_code -->

Code :
multimap<string, class Client*> m;

<!-- END TEMPLATE: bbcode_code -->Ainsi que l'insertion :

<!-- BEGIN TEMPLATE: bbcode_code -->

Code :
m.insert(make_pair(clien.getnom(),&clien));

<!-- END TEMPLATE: bbcode_code -->Et l'affichage :

<!-- BEGIN TEMPLATE: bbcode_code -->

Code :
for( it=m.begin() ; it != m.end(); it++ )
cout << "Clef : " << (*it).first << endl << "Client :" << *(*it).second << endl;

<!-- END TEMPLATE: bbcode_code -->Mais le problème devient que le contenu de la multimap ne change pas pour ce qui est de la donnée, la clé change mais l'objet affiché correspond au dernier client saisi.

Merci d'avance pour votre aide, qui nous serait très précieuse!!

<!-- / message -->
<!-- edit note -->

4 réponses

BunoCS Messages postés 15475 Date d'inscription lundi 11 juillet 2005 Statut Modérateur Dernière intervention 23 avril 2024 103
23 mai 2008 à 17:03
Salut,
Y'a un truc qui me chiffonne: dans la fonction "nouveauClient", tu crée une variable locale, tu joue avec...et tu la retournes!! Pas bien... En effet, toute variable locale est détruite en sortie de fonction: il faut, soit passer un objet en paramètre de ta fonction, soit allouer un pointeur et retourner ce pointeur.

Mais bon, si ta map doit contenir beaucoup d'objet, c'est mieux d'y stocker des pointeurs...

En espérant avoir répondu à la question.

Buno
----------------------------------------
L'urgent est fait, l'impossible est en cours. Pour les miracles, prévoir un délai...
Le site de mon mariage
3
luhtor Messages postés 2023 Date d'inscription mardi 24 septembre 2002 Statut Membre Dernière intervention 28 juillet 2008 6
23 mai 2008 à 17:21
"En effet, toute variable locale est détruite en sortie de fonction: il
faut, soit passer un objet en paramètre de ta fonction, soit allouer un
pointeur et retourner ce pointeur."
=> Mais non, je sais pas d'ou ca sort ca. On a vu plusieurs fois cette remarque et c'est faux. Aucun pb à retourner un objet local tant qu'on en stocke pas le pointeur.

Pour ton pb, soit ta classe est incorrecte. Soit le pb est ailleurs, mais tu postes trop peu de code pour qu'on puisse analyser quoi que ce soit.
0
elnino67 Messages postés 3 Date d'inscription jeudi 22 mai 2008 Statut Membre Dernière intervention 29 mai 2008
23 mai 2008 à 17:32
J'ai manipulé un petit peu ma fonction en renvoyant un pointeur, et effectivement cela a résolu tous mes problèmes..
Pour autant luthor ton avis m'intéresse!On m'a moi aussi appris qu'une variable définie localement n'a une durée de vie équivalente uniquement à la fonction où elle est définie..Pourrais-tu m'en dire plus sur ce en quoi tu crois toi?

PS: Merci beaucoup Buno!!
0
luhtor Messages postés 2023 Date d'inscription mardi 24 septembre 2002 Statut Membre Dernière intervention 28 juillet 2008 6
23 mai 2008 à 18:24
int main()
{
    float value = sqrtf(10.0f);
    return 0;
}

Si l'objet retourné était invalide, on ne pourrait pas écrire ces quelques lignes puisque la valeur retourner par sqrtf est bien locale à la fonction... Or ce qui est vrai ici l'est aussi pour n'importe quel objet. Un objet alloué localement et retourné par la fonction reste  valide jusqu'à sa destruction, c'est à dire après que l'on ait pu en récupérer la valeur.

Pour clarifier, voici un exemple clair. Tu peux éxécuter ce code, le résultat est à la fin du post.

#include

class Test
{
    public:
       
        Test() { std::cout << "constructeur" << std::endl; }
        Test(const Test &) { std::cout << "copie" << std::endl; }
        ~Test() { std::cout << "destructeur" << std::endl; }
       
        Test & operator = (const Test &)
        {
            std::cout << "affectation" << std::endl;
           
            return *this;
        }
};

Test BuildObject()
{
    std::cout << "fonction" << std::endl;
   
    Test ret;
   
    return ret;
}

int main(int argc, char *argv[])
{
    {
        Test obj1;
       
        obj1 = BuildObject();
    }
   
    system("PAUSE");
   
    return 0;
}

Et voici un résultat de run:

constructeur            => Constructeur de "Test obj1:"
fonction                  => Dans la fonction BuildObject
constructeur           => Constructeur de l'objet local a la fonction "Test ret;"
affectation             => Objet local renvoyé par la fonction, envoyé en argument à l'affectation (opérateur = )
destructeur           =>Destructeur de l'objet retourné par la fonction
destructeur             => Destructeur de "Test obj1;"
Appuyez sur une touche pour continuer...

Comme on le voit et heureusement, le destructeur de l'objet qui est retourné par la fonction est appelé après l'affectation !
Ce qui n'est pas possible c'est de décupérer l'adresse de cet objet, puisqu'il va etre détruit après etre passé dans l'opérateur d'affectation (=).

Donc oui tes lignes étaient correctes, le pb est ailleurs. C'est le débuggeur qui aurait pu te donner les pistes pour comprendre le vrai problème.
0
Rejoignez-nous