Pointeurs intelligents et liste chainée

Pointeurs intelligents et liste chainée - C++ - Programmation

Marsh Posté le 04-04-2006 à 20:06:02    

Bonjour,
 
Je voulais savoir si quelqu'un avait déjà implémenter une liste chainée avec des "smart pointers" ?
 
Je pensais faire quelque chose comme ça (tiré du chapitre 16 de la FAQ C++ Lite):

Code :
  1. class FredPtr;
  2. class Fred {
  3.     public:
  4.       static FredPtr create()             { return new Fred(); }
  5.       static FredPtr create(int i, int j) { return new Fred(i,j); }
  6.        // ...
  7.     private:
  8.       friend class FredPtr;      // Une classe amie  
  9.       unsigned count_;
  10.       Fred():count_(0);
  11.       Fred(int i, int j):count_(0);
  12.       FredPtr Suivant;
  13.        // ...
  14.     };
  15. class FredPtr {
  16.     public:
  17.       Fred* operator-> () { return p_; }
  18.       Fred& operator* ()  { return *p_; }
  19.       FredPtr(Fred* p)    : p_(p) { ++p_->count_; }   // p ne doit pas valoir NULL
  20.      ~FredPtr()           { if (--p_->count_ == 0) delete p_; }
  21.       FredPtr(const FredPtr& p) : p_(p.p_) { ++p_->count_; }
  22.       FredPtr& operator= (const FredPtr& p)
  23.             {  // NE CHANGEZ PAS L'ORDRE DE CES INSTRUCTIONS!
  24.                // (Cet ordre gère correctement le cas de l'auto-affectation)
  25.               ++p.p_->count_;
  26.               if (--p_->count_ == 0) delete p_;
  27.               p_ = p.p_;
  28.               return *this;
  29.             }
  30.     private:
  31.       Fred* p_;     // p_ ne vaut jamais NULL
  32.     };


Mais lors de la compilation il me met une erreur comme quoi le type de Suivant n'est pas défini (invalid use of undefined type et forward declaration of 'struct FredPtr') et le résultat des fonction create non plus...en somme il ne reconnait pas la classe FredPtr dans la classe Fred.
 
Qu'ai je fait de mal ?
 
Question subsidiaire : est ce une bonne idée de faire une liste chainée avec des "smart pointers" ?


Message édité par Alban44 le 04-04-2006 à 20:32:12
Reply

Marsh Posté le 04-04-2006 à 20:06:02   

Reply

Marsh Posté le 04-04-2006 à 20:31:06    

> est ce une bonne idée de faire une liste chainée avec des "smart pointers" ?
 
J'aurai tendance à dire non... les smart pointers ne devraient pas être stockés en dehors de la pile principale (sinon ils ne sont plus <<smart>> ). En plus c'est de la bidouille.

Reply

Marsh Posté le 04-04-2006 à 20:35:39    

> class FredPtr;
Te permet d'utiliser des pointeurs (des vrais) sur FredPtr, sinon le compilo ne connait pas la taille de cette classe au moment où il essaye de compiler la classe Fred.

Reply

Marsh Posté le 04-04-2006 à 20:36:14    

nargy a écrit :

> est ce une bonne idée de faire une liste chainée avec des "smart pointers" ?
 
J'aurai tendance à dire non... les smart pointers ne devraient pas être stockés en dehors de la pile principale (sinon ils ne sont plus <<smart>> ). En plus c'est de la bidouille.


 
Ok je comprends, alors comment géré proprement une liste doublement chainée dont les noeuds sont eux-memes des listes chainées ?
 
Au bout d'un moment le prog crash.

Reply

Marsh Posté le 04-04-2006 à 20:41:57    

nargy a écrit :

> class FredPtr;
Te permet d'utiliser des pointeurs (des vrais) sur FredPtr, sinon le compilo ne connait pas la taille de cette classe au moment où il essaye de compiler la classe Fred.


 
Si je te comprends bien, il faut que mes fonctions create renvoient un FredPtr*...et dans ce cas je perds l'interet du "smart pointer" d'ou ta premiere réponse...C'est ça ?
 

Reply

Marsh Posté le 04-04-2006 à 20:45:46    

Le meilleur moyen reste de bien cloisonner ton code:

  • tu fait un template de liste chaînée, que tu peut réutiliser à volonté,
  • il ya deux types de listes: autodelete ou pas, autodelete supprime les éléments lorsque la lise est détruite (gare aux pointeurs qui traînent, les smart pointers ne t aideront pas), tu peut passer <bool autodelete> à un template,
  • tu gère proprement la destruction de tes objets.

Reply

Marsh Posté le 04-04-2006 à 20:49:34    

Merci de ton aide car sans ça je m'orientais vers une impasse.

Reply

Marsh Posté le 04-04-2006 à 20:55:24    

Un exemple, avec autodelete en dehors du template, mais tu peut le modifier pour linclure dans le template (différence: ne peut changer l autodelete au runtime, mais plus optimisé).
 

Code :
  1. template <class Element> class DList
  2. {
  3.   class DListCell
  4.   {
  5.     public:
  6.     Element* e;
  7.     DListCell* prev;
  8.     DListCell* next;
  9.   };
  10.   DListCell* _list;
  11.   DListCell* _last;
  12.   bool _autodelete;
  13.   public:
  14.   DList(bool autodelete=1):_list(0),_last(0),_autodelete(autodelete) {}
  15.   ~DList()
  16.   {
  17.     for(DListCell* c=_list;c;)
  18.     {
  19.       DListCell* next=c->next;
  20.       if (_autodelete) delete c->e;
  21.       delete c;
  22.       c=next;
  23.     }
  24.   }
  25.   void setAutoDelete(bool a)
  26.   { _autodelete=a; }
  27.   class Index
  28.   {
  29.     DListCell* _current;
  30.     Index(DListCell* c): _current(c) {}
  31.     public:
  32.     Index(): _current(0) {}
  33.     Index(DList<Element>* list): _current(list->_list) {}
  34.     Index& next()
  35.     {
  36.       if (_current)
  37.         _current=_current->next;
  38.       return *this;
  39.     }
  40.     bool end() const
  41.     { return !_current; }
  42.     Element* operator -> () const
  43.     { return _current->e; }
  44.     friend class DList<Element>;
  45.   };
  46.   Element* operator [] (const Index& i) const
  47.   { return i._current->e; }
  48.   Index append(Element* e)
  49.   {
  50.     DListCell* c=new DListCell();
  51.     c->e=e;
  52.     c->next=0;
  53.     c->prev=_last;
  54.     if(_last)
  55.     {
  56.       _last->next=c;
  57.       _last=c;
  58.     }
  59.     else
  60.       _list=_last=c;
  61.     return Index(c);
  62.   }
  63.   Element* remove(Index& i)
  64.   {
  65. if (!i._current) fprintf(stderr,"DList::Index: removeing null!\n" );
  66.     if (i._current)
  67.     {
  68.       DListCell* c=i._current;
  69.       Element* r=c->e;
  70.       if(c==_list)
  71.       {
  72.         _list=_list->next;
  73.         if (_list)
  74.           _list->prev=0;
  75.       }
  76.       else if (c==_last)
  77.       {
  78.         _last->prev->next=0;
  79.         _last=_last->prev;
  80.       }
  81.       else
  82.       {
  83.         c->next->prev=c->prev;
  84.         c->prev->next=c->next;
  85.       }
  86.       i._current=c->next;
  87.       return r;
  88.     }
  89.     return 0;
  90.   }
  91. };


Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed