title: Simple reference counting: smart pointers
body: <p>I would like to implement a simple reference counting using smart pointers. The variable <code>pointer</code> represents pointer to stored object, <code>reference_count</code> represents total count of copies of the object.</p>
  
  <ul>
  <li>if we initialize an object using NULL: reference_count = -1 else reference_count = 1</li>
  <li>copy ctor and operator = increment reference_count</li>
  <li>destructor decrement reference_count and if there is no other reference to pointed object performs its deletion.</li>
  </ul>
  
  <p>Here is my code:</p>
  
  <pre><code>#ifndef smart_pointer_H
  #define smart_pointer_H
  
  template &lt; typename T &gt; class smart_pointer
  {
      private:
          T*    pointer;      
          int reference_count;    
  
      public:
  
          smart_pointer() : pointer(0), reference_count(-1) {}
  
          smart_pointer(T* p) : pointer(p)
          {
              if (p != NULL)
              {
                  this-&gt;reference_count = 1;
              }
  
              else
              {
                  this-&gt;reference_count = -1;
              }
          }
  
          smart_pointer(const smart_pointer &lt;T&gt; &amp; p) : pointer(p.pointer),     reference_count(p.reference_count + 1) {}
          bool operator == (const smart_pointer &lt;T&gt;&amp; p) { return pointer == p.pointer; }
          bool operator != (const smart_pointer &lt;T&gt;&amp; p) { return pointer != p.pointer; }
  
  
          ~ smart_pointer()
          {
              if(-- reference_count == 0)
          {
                  std::cout &lt;&lt; "Destructing: " &lt;&lt; '\n';
                  delete pointer;
              }
          }
  
          T&amp; operator *  () { return *pointer; }
          T* operator -&gt; () { return pointer; }
  
          smart_pointer &lt;T&gt; &amp; operator = (const smart_pointer &lt;T&gt; &amp; p)
          {
                  if (this != &amp;p)
                  {
                      if( -- reference_count == 0)
                      {
                          delete pointer;
                      }
  
                          pointer = p.pointer;
                          reference_count = p.reference_count + 1;
                  }
  
          return *this;
          }
  };    
  </code></pre>
  
  <p>Here is my testing code, class sample stores 2D point and two pointers to any other 2D points.</p>
  
  <pre><code>template &lt; typename T &gt;
  class smart_pointer;
  
  class Point
  {
  private:
      double x, y;
      smart_pointer &lt;Point&gt; p1;
      smart_pointer &lt;Point&gt; p2;
  
  public:
      Point(double xx, double yy): x(xx), y(yy) {this-&gt; p1 = NULL; this-&gt;p2 = NULL;}
      Point(double xx, double yy, smart_pointer &lt;Point&gt; p1, smart_pointer &lt;Point&gt; p2): x(xx), y(yy) {this-&gt; p1 = p1, this-&gt;p2 = p2; }
      double getX(){ return x;}
      double getY(){ return y;}
      void setX(double xx)  {this-&gt;x = xx;}
      void setY(double yy)  {this-&gt;y = yy;}
      void setP1(smart_pointer &lt;Point&gt; p1) {this-&gt;p1 = p1;}
      void setP2(smart_pointer &lt;Point&gt; p2) {this-&gt;p2 = p2;}
  
      void print()
      {
           std::cout &lt;&lt; "x= " &lt;&lt; x &lt;&lt; " y= " &lt;&lt; y &lt;&lt; '\n';
           std::cout &lt;&lt; "p1" &lt;&lt; '\n';
           if (p1 != NULL)
           {
               p1-&gt;print();
           }
           std::cout &lt;&lt; "p2" &lt;&lt; '\n';
           if (p2 != NULL)
           {
              p2-&gt;print();
           }
           std::cout &lt;&lt; '\n';
      }
  
  };
  </code></pre>
  
  <p>List of 2D points:</p>
  
  <pre><code>#include "Point.h"
  
  class PointsList
  {
  private:
      std::vector &lt;smart_pointer &lt;Point&gt; &gt; points;
  
  public:
      smart_pointer &lt;Point&gt; &amp; operator [] ( int index ) {return points[index];}
  
  public:
      void push_back(smart_pointer &lt;Point&gt; p) {points.push_back(p);}
      void erase(unsigned int index) {points.erase(points.begin() += index );}
      void printPoints()
      {
          std::cout &lt;&lt; "List of points" &lt;&lt; '\n';
          for (unsigned int i = 0; i &lt; points.size();  i++)
          {
              points[i]-&gt;print();
  
          }
  
      }
  };
  </code></pre>
  
  <p>Test code: </p>
  
  <pre><code>#include "Point.h"
  #include "PointsList.h"
  
  int main()
  {
      smart_pointer &lt;Point&gt; pb = NULL;
      pb = (new Point(0,0));
      smart_pointer &lt;Point&gt; p0(new Point(0,0));
      p0-&gt;print();
      smart_pointer &lt;Point&gt; p1(new Point(10,10));
      p1-&gt;print();
      smart_pointer &lt;Point&gt; p2(new Point(20,20));
      p2-&gt;print();
      smart_pointer &lt;Point&gt; p3(new Point(30,30));
      p3-&gt;print();
  
      smart_pointer &lt;Point&gt; pa(p3);
      p0-&gt;setP1(p2);
      p0-&gt;setP2(p3);
      p0-&gt;print();    
      p0 = p1;
      p0-&gt;print();
      p0-&gt;print();
  
      PointsList pl1;
      pl1.push_back(p0);
      pl1.push_back(p1);
  
      PointsList pl2;
      pl2.push_back(p2);
      pl2.push_back(p3);
      pl1.erase(0);
      pl1.printPoints();
      pl2.printPoints();
      return 0;
  }
  </code></pre>
  
  <p>Where are advanteges or disadvanteges of such solution? What about running speed for huge amount of data, casting, possible problems with inheritance, etc. Thanx for your help.</p>
  
  <p>I had <strong>one more question</strong> to this example: Which type of the smart pointer (shared, scoped) would be  for such a data structures the most suitable:</p>
  
  <pre><code>//Class with cross-references to points p1, p2
  class PointTopo
  {
  private:
      double x, y;
      PointTopo * p1;
      Point * p2;
  
  public:
      PointTopo(double xx, double yy): x(xx), y(yy) {this-&gt; p1 = NULL; this-&gt;p2 = NULL;}
      ...
  </code></pre>
  
  <p>};</p>
  
  <pre><code>//Class  with cross references: topological model for Delaunay triangulation
  class Edge
  {
     private:
        Point2D * start;
        Edge *next;
        Edge *previous;
        Edge *twin;
  ...
  };
  </code></pre>
  
  <p>Thanks for your help...</p>