|
  |
[C++]Fun with pointers |
|
|
|
|
5/11/2009, 15:03
|

I know where you live
      
Groupe : Membre
Messages : 4 934
Inscrit : 22/7/02
Lieu : Liège
Membre no 1 639
Steam : [GZ]Lupuss

|
Salut les geeks, j'ai remis mes gros doigts dans du C++ et j'ai qq difficultés avec nos amis les pointeurs. Donc imaginons une classe lambda avec plusieurs variables membres qui sont des pointeurs char* (oui, String tout ça, je sais, mais ce n'est pas le but ici). Ces pointeurs son mis à null dans les constructeurs, et puis j'appelle les différents setters. Dans les setters de chaque variable de type pointeur, je commence par faire un delete (le pointeur sera toujours valide ou null normalement) puis un new (ce sera plus lisible dans le code je pense). Un exemple de classe avec deux pointeurs char* (nom et prenom) et deux entiers (age et taille): CODE Personne::Personne(){ cerr << "[Personne] Constructeur par défaut" << endl;
nom = NULL; prenom = NULL; setNom(NULL); setPrenom(NULL); setAge(18); setTaille(175); } un setter typique: CODE void Personne::setNom(const char* const nom){ delete this->nom; //QUESTION: serait-il utile de mettre le pointeur à null ici? des explications? this->nom = new char[nom ? strlen(nom) : 0 + 1];
if(nom) strcpy(this->nom, nom); else *this->nom = 0; }
--------------------
"Le tagging de cul c'est tellement 2.0 ça, j'adore"Ah yes, the videotaped blowjob, the mark of a society that has finally made it to the big time. 
|
|
|
|
|
|
|
|
|
|
5/11/2009, 15:59
|

Don't worry - Be happy
      
Groupe : Membre
Messages : 4 134
Inscrit : 23/4/02
Lieu : Lyon
Membre no 512
PSN : Nebsorg
Xbox Live : Nebsorg

|
Citation (Lupuss @ 5/11/2009, 15:03)  Salut les geeks, j'ai remis mes gros doigts dans du C++ et j'ai qq difficultés avec nos amis les pointeurs. Plusieurs remarques : * pourquoi tu fais CODE nom = null; puis setnom(null)
si tu fais ton nom = null, ton setnom derriere sert a rien. Et ton delete de ton setnom arrivera sur rien, vu que tu aura deja fait nom=null Pourquoi, si le nom que tu passes est null, tu fais un *this->nom = 0 et pas = null ? Moi je ferai ca : CODE void Personne::setNom(const char* const nom){
delete this->nom;
if (nom != null) { this->nom = new char[strlen(nom)]; strcpy(this->nom, nom); } else { this->nom = null; }
}
Ce message a été modifié par cben76 - 5/11/2009, 16:02.
--------------------
|
|
|
|
|
|
|
|
5/11/2009, 16:18
|

Senseï Geek
    
Groupe : Membre
Messages : 1 408
Inscrit : 20/7/05
Lieu : Valenciennes
Membre no 12 205

|
Bizarre ton code. Un conseil, prends l'habitude de nommer les données membres de ta classe ainsi "m_nomdelavariable". Et fait commencer le nom de tes classes par un C (comme classe). Puis d'autres détails. Je remets une partie de ton code à jour pour en espérant répondre à ta question  (j'ai pas bien compris ce que tu voulais) Code void CPersonne::setNom(const char* const pcstrNom) { if (pcstrNom == NULL) return;
if (m_pstrNom != NULL) // pour éviter de mauvaises surprises { delete m_pcstrNom; m_pstrNom = null; }
m_pstrNom = new char[strlen(pcstrNom)]; strcpy(m_pstrNom, pcstrNom); } edit: Avant qu'on me fasse la remarque, oui je sais le code peut être encore simplifié
Ce message a été modifié par Tomma - 5/11/2009, 16:34.
--------------------
|
|
|
|
|
|
|
|
5/11/2009, 20:47
|
Little Geek

Groupe : Membre
Messages : 11
Inscrit : 7/5/08
Membre no 17 335
Steam : skeetmtp
Xbox Live : skitor

|
Je vais essayer repondre uniquement a la question, meme si j'ai un doute sur la question en elle meme : 1) si la question etait, est-ce qu'il faudrait pas ajouter un this->nom = 0; apres le delete comme ca : Code void Personne::setNom(const char* const nom){ delete this->nom; this->nom = 0; //comme ca ?? this->nom = new char[nom ? strlen(nom) : 0 + 1]; if(nom) strcpy(this->nom, nom); else *this->nom = 0; } clairement non aucun interet. 2) si la question etait, est-ce qu'il faudrait pas laisser le pointeur null au lieu d'allouer une chaine vide comme ca : Code void Personne::setNom(const char* const nom){ delete this->nom; if(this->nom) { this->nom = new char[strlen(nom) + 1]; strcpy(this->nom, nom); } else this->nom = 0; } moi ca me parait plus coherent de remetre le pointeur a null vu que ca le remet dans l'etat ou il etait apres etre passé par le constructeur
|
|
|
|
|
|
|
|
6/11/2009, 00:10
|

I know where you live
      
Groupe : Membre
Messages : 4 934
Inscrit : 22/7/02
Lieu : Liège
Membre no 1 639
Steam : [GZ]Lupuss

|
Je viens d'éplucher le code en revue avec un pote, les erreurs étaient en fait dues à tout autre chose, mais j'en ai profité pour revoir la classe, et je pense que le résultat est plus propre comme cela: D'abord le constructeur: CODE Personne::Personne() : nom(NULL), prenom(NULL), ident(NULL), age(18), taille(175){ cerr << "[Personne] Constructeur par défaut" << endl;
//setNom("xxx"); } un setter et un getter: CODE void Personne::setNom(const char* const nom){ delete[] this->nom;
if(nom){ this->nom = new char[strlen(nom) + 1]; strcpy(this->nom, nom); } else this->nom = NULL; }
const char* const Personne::getNom() const{ return nom ? nom : ""; } Voilà, je ne m'amuse plus à allouer un octet pour rien, et le constructeur s'en trouve bien simplifié aussi (vive les initlists). ça vous parait moins horrible?
--------------------
"Le tagging de cul c'est tellement 2.0 ça, j'adore"Ah yes, the videotaped blowjob, the mark of a society that has finally made it to the big time. 
|
|
|
|
|
|
|
|
6/11/2009, 11:23
|
Padawan Geek
 
Groupe : Membre
Messages : 143
Inscrit : 21/10/06
Lieu : Paris
Membre no 14 921

|
Point par point, pour la base : 1/ Une donnée membre pointeur ça s'initialise à NULL dans le constructeur (ou alors avec une donnée pré-établie). 2/ Il faut toujours mettre en place un déstructeur qui fasse le delete() des pointeurs de cette manière : CODE if (this->monpointeur != NULL) { delete(this->monpointeur); this->monpointeur = NULL; }
3/ Dans le setter tu dois faire le delete du pointeur s'il est non-nul avant de réaffecter la nouvelle adresse pointée : CODE public void setMonpointeur(void* pointeur) { if (this->monpointeur != NULL) { delete(this->monpointeur); } this->monpointeur = refpointeur; }
4/ A l'appel du getter toujours vérifier si le pointeur reçu est NULL avant de l'utiliser. Après, le plus propre c'est de mettre en place des smart pointers (pointeurs intelligents), soit toi-même, soit via une lib (Boost par exemple).
|
|
|
|
|
|
|
|
7/11/2009, 17:29
|

Padawan Geek
 
Groupe : Membre
Messages : 241
Inscrit : 22/4/03
Lieu : Rueil Malmaison
Membre no 3 758

|
Mon petit grain de sel: Citation delete[] this->nom; Pas de delete[], tu n'as pas alloué de tableau d'objet mais un tableau de type primitif. En général, le compilateur s'en sort, mais c'est pas beau quand meme.
Ce message a été modifié par Trevidos - 7/11/2009, 17:30.
--------------------
|
|
|
|
|
|
|
|
9/11/2009, 02:09
|

Build succeeded !
   
Groupe : Modérateurs
Messages : 983
Inscrit : 2/4/02
Lieu : edinburgh
Membre no 60

|
Pour en rajouter un peu, je trouve que ton getter peut etre dangereux: tu retourne l'adresse d'une constante probablement cree sur la pile (le ""), si l'appelant s'avise de garder le pointeur pour (beaucoup) plus tards, tu risques, selon le compilo et la plateforme, de tomber sur un bout de memoire pas frais. A ta place, soit je retournerais juste "nom", et c'est a l'appelant de gerer le NULL, soit je retournerais l'adresse d'une constante vide, genre un "static const char[] = """. Mais en fait je retournerais NULL.
Valavala.
--------------------
c0unt0 Hey, nice marmot!
|
|
|
|
|
|
|
  |
1 utilisateur(s) sur ce sujet (1 invité(s) et 0 utilisateur(s) anonyme(s))
0 membre(s) :
|