智能指针,或“更好”的析构函数

时间:2010-09-01 16:11:06

标签: c++ destructor reference-counting datamodel smart-pointers

哪种类型的智能指针(共享,作用域)最适合这样的数据结构......

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

};

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

我想使用vector存储Edges和PointTopo:

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

}

但是析构函数存在问题,所以我想知道是否使用引用计数。

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
}

点p1,p2将存储在列表t1,tl2中。 tl2的析构函数导致异常,使用tl1析构函数删除了点p1和p2。

此示例不是合成的。想象一下,nl2代表nl1的子集,例如nl1的凸包......

我认为,如果没有引用计数,这个问题就无法解决......所以我尝试使用一些智能指针......

非常感谢你的帮助......

3 个答案:

答案 0 :(得分:2)

  

tl2的析构函数导致异常,使用tl1析构函数删除了点p1和p2。

您正尝试delete对象p1(和p2)两次。这会引发UB - 这是一件坏事。尝试在shared_ptr命名空间中可用的std::tr1(引用计数智能指针)(有关详细信息,请参阅编译器文档)或Boost。

另一件事是复制对象(而不是现在正在执行的指针)。这需要复制PointTopo个对象。

(就我个人而言,我倾向于unique_ptrEdge成员单独使用PointTopo。)

答案 1 :(得分:2)

shared_ptr<>确实引用了对同一个对象的几个指针的计数和管理,当对象的最后一个指针被销毁时删除该对象。

scoped_ptr<>使指针的行为类似于堆栈变量,只要指针超出范围,它就会删除指向的对象。这不是你在这里寻找的行为。

在您的用例中,shared_ptr<>提供的引用计数是您想要的。

答案 2 :(得分:1)

你需要的是一个boost :: shared_ptr