STL: Problème stockage dans un container multimap [Résolu]

Signaler
Messages postés
3
Date d'inscription
jeudi 22 mai 2008
Statut
Membre
Dernière intervention
29 mai 2008
-
Messages postés
2023
Date d'inscription
mardi 24 septembre 2002
Statut
Membre
Dernière intervention
28 juillet 2008
-
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

Messages postés
14881
Date d'inscription
lundi 11 juillet 2005
Statut
Modérateur
Dernière intervention
27 novembre 2020
93
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
Messages postés
2023
Date d'inscription
mardi 24 septembre 2002
Statut
Membre
Dernière intervention
28 juillet 2008
5
"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.
Messages postés
3
Date d'inscription
jeudi 22 mai 2008
Statut
Membre
Dernière intervention
29 mai 2008

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!!
Messages postés
2023
Date d'inscription
mardi 24 septembre 2002
Statut
Membre
Dernière intervention
28 juillet 2008
5
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.