views:

79

answers:

3

Which type of the smart pointer (shared, scoped) would be for such a data structures the most suitable...

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;
...
};

I would like to store Edges and PointTopo using vector:

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();
        }

}

But there are problems with destructor, so I wondered whether or not to use reference counting.

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
}

Points p1, p2 will be stored in both list, tl1, tl2. Destructor of tl2 causes an exception, points p1 and p2 has already been deleted using tl1 destructor.

This example is not synthetic. Imagine, that nl2 represents subset of nl1, for example the convex hull of nl1...

I think, that this problem could not be solved without refererence counting... So I try to use some smart pointer...

Thank you very much for your help...

+1  A: 

what you require is a boost::shared_ptr

aeh
+2  A: 

Destructor of tl2 causes an exception, points p1 and p2 has already been deleted using tl1 destructor.

You are trying to delete the object p1 (and p2) twice. That invokes UB -- a Bad Thing to do. Try shared_ptr (reference counted smart pointers) which is available both in std::tr1 namespace (see your compiler documentation for further details) or Boost.

The other thing to do is to copy the objects (and not the pointers as you are doing now). And that'd required duplicating PointTopo objects.

(Personally, I'd be inclined to use unique_ptr for members of Edge and PointTopo in isolation.)

dirkgently
+2  A: 

shared_ptr<> does reference counting and management of several pointers to the same object, deleting the object when the last pointer to it is destroyed.

scoped_ptr<> makes a pointer behave like a stack variable, it deletes the pointed-to object as soon as the pointer goes out of scope. This not the behavior you are looking for here.

In your use case the reference counting provided by shared_ptr<> is what you want.

sth
Working with pointers is very fast... Does the speed of the program significantly decrease using shared_ptr?
Ian
@Ian: No, most likely not. Basically creating pointer variables, copying them and destroying them is faster than their equivalents on smart pointers. But unless thats that main thing your program does it's unlikely you'll see a difference. *Dereferencing* (aka. actually using the pointed-to data) should be equally fast.
sth
@Ian, the only overhead should be on assigning and destroying the pointer. The accesses should be through inline functions, and a good compiler will optimize away that code so that it's the same as a raw pointer.
Mark Ransom
@Ian - if you do find speed to be an issue then you could try intrusive versions. They require you modify the objects you're going to point to, but won't have the extra reference count object creation and such. I doubt you'll even notice, but if you do that's an option.
Noah Roberts
ReferenceCounting do add performance overhead of course. But in reality only very specific cases suffer from it as the overhead is low. shared_ptr<> do however significantly improve the robustness and readability of C++ code. That in turn helps the "developer performance" something that in most cases is more significant than theoratical performance impact from using reference counting.
FuleSnabel
To my question... Construction of the Delaunay triangulation for 1E6 points needs approx. 3E6 halfeges linked by pointers. Could be a problem vector of 3E6 shared_ptrs represented by edges?
Ian