2010-09-01 28 views
2

Quel type de pointeur intelligent (partagé dont la portée a) serait pour une telle structure de données les plus appropriées ...pointeurs intelligents, ou "mieux" destructor

Structure 1:

//Class with cross-references to points p1, p2 
class PointTopo 
{ 
private: 
    double x, y; 
    PointTopo * p1; 
    PointTopo * p2; 

public: 
    PointTopo(double xx, double yy): x(xx), y(yy) {this-> p1 = NULL; this->p2 = NULL;} 
    ... 

} ;

Structure 2:

//Class with cross references: topological model for Delaunay triangulation 
class Edge 
{ 
    private: 
     Point * start; //Only 2D point without topo information 
     Edge *next; 
     Edge *previous; 
     Edge *twin; 
... 
}; 

Je voudrais stocker Arêtes et PointTopo en utilisant le vecteur:

class PointsTopoList 
{ 
    private: 
     std::vector <PointTopo *> points; 
    public: 

     inline void push_back (PointTopo *p) { points.push_back (p);} 
     ~PointsTopoList() {clear();} 
     void clear() 
     { 
      for (TNodes2DList::iterator i_points= points.begin(); i_points!= points.end(); ++i_points) 
      { 
      if (*i_points!= NULL) 
      { 
       delete *i_points; 
       *i_points= NULL; 
      } 

      points.clear(); 
     } 

} 

Mais il y a des problèmes avec destructor, donc je me demandais si vous souhaitez utiliser le comptage de référence ou non.

int main() 
{ 
    PointTopo *p1 = new PointTopo(0,0); 
    PointTopo *p2 = new PointTopo(10,10); 
    PointTopo *p3 = new PointTopo(20,20); 
    PointTopo *p4 = new PointTopo(30,30); 

    PointsTopoList tl1; 
    tl1.push_back(p1); 
    tl1.push_back(p2); 
    tl1.push_back(p3); 
    tl1.push_back(p4); 

    PointsTopoList tl2; 
    tl2.push_back(p1); //P1 is stored in tl1 and tl2 
    tl2.push_back(p2); //P2 is stored in tl1 and tl2 
} 

Les points p1, p2 seront stockés dans les deux listes, tl1, tl2. Destructeur de tl2 provoque une exception, les points p1 et p2 ont déjà été supprimés en utilisant tl1 destructor.

Cet exemple n'est pas synthétique. Imaginez, que nl2 représente le sous-ensemble de nl1, par exemple la coque convexe de nl1 ...

Je pense que ce problème ne pouvait pas être résolu sans comptage de référence ... Alors j'essaie d'utiliser un pointeur intelligent ...

Merci beaucoup pour votre aide ...

Répondre

1

ce que vous avez besoin est un coup de pouce :: shared_ptr

2

Destructeur de TL2 provoque une exception, les points p1 et p2 a déjà été supprimé à l'aide TL1 destructeur.

Vous essayez de delete l'objet p1 (et p2) deux fois. Cela invoque UB - une mauvaise chose à faire. Essayez shared_ptr (pointeurs intelligents comptés par référence) qui est disponible dans l'espace de noms std::tr1 (voir la documentation de votre compilateur pour plus de détails) ou Boost.

L'autre chose à faire est de copier les objets (et non les pointeurs comme vous le faites maintenant). Et cela aurait nécessité de dupliquer les objets PointTopo.

(Personnellement, je serais enclin à utiliser unique_ptr pour les membres de Edge et PointTopo dans l'isolement.)

2

shared_ptr<> comptage et la gestion ne fait référence de plusieurs pointeurs vers le même objet, suppression de l'objet lorsque le dernier pointeur à elle est détruite.

scoped_ptr<> fait qu'un pointeur se comporte comme une variable de pile, il supprime l'objet pointé dès que le pointeur sort de la portée. Ce n'est pas le comportement que vous recherchez ici.

Dans votre cas d'utilisation, le comptage de référence fourni par shared_ptr<> est ce que vous voulez.

+0

Travailler avec des pointeurs est très rapide ... La vitesse du programme diminue-t-elle significativement en utilisant shared_ptr? – Ian

+2

@Ian: Non, très probablement pas.Fondamentalement, créer des variables pointeur, les copier et les détruire est plus rapide que leurs équivalents sur les pointeurs intelligents. Mais à moins que ce soit ce que votre programme fait, il est peu probable que vous verrez une différence. * Déréférencement * (aka en utilisant réellement les données point-à) devrait être tout aussi rapide. – sth

+1

@Ian, le seul surcoût devrait être d'assigner et de détruire le pointeur. Les accès doivent passer par des fonctions en ligne, et un bon compilateur optimisera ce code pour qu'il soit le même qu'un pointeur brut. –