Simple comptage de référence: pointeurs intelligents

J'aimerais implémenter un simple comptage de référence à l'aide des pointeurs intelligents. La variable pointer représente pointeur d'objet stocké, reference_count représente le total de nombre de copies de l'objet.

  • si nous initialiser un objet à l'aide de la valeur NULL: reference_count = -1 else reference_count = 1
  • copie ctor et l'opérateur = incrément de reference_count
  • destructeur de décrémentation reference_count et si il n'y a pas d'autre référence à l'objet pointé effectue sa suppression.

Voici mon code:

#ifndef smart_pointer_H
#define smart_pointer_H
template < typename T > 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->reference_count = 1;
}
else
{
this->reference_count = -1;
}
}
smart_pointer(const smart_pointer <T> & p) : pointer(p.pointer),     reference_count(p.reference_count + 1) {}
bool operator == (const smart_pointer <T>& p) { return pointer == p.pointer; }
bool operator != (const smart_pointer <T>& p) { return pointer != p.pointer; }
~ smart_pointer()
{
if(-- reference_count == 0)
{
std::cout << "Destructing: " << '\n';
delete pointer;
}
}
T& operator *  () { return *pointer; }
T* operator -> () { return pointer; }
smart_pointer <T> & operator = (const smart_pointer <T> & p)
{
if (this != &p)
{
if( -- reference_count == 0)
{
delete pointer;
}
pointer = p.pointer;
reference_count = p.reference_count + 1;
}
return *this;
}
};    

Voici mon code de test, la classe de l'échantillon magasins 2D point et deux pointeurs vers les autres points 2D.

template < typename T >
class smart_pointer;
class Point
{
private:
double x, y;
smart_pointer <Point> p1;
smart_pointer <Point> p2;
public:
Point(double xx, double yy): x(xx), y(yy) {this-> p1 = NULL; this->p2 = NULL;}
Point(double xx, double yy, smart_pointer <Point> p1, smart_pointer <Point> p2): x(xx), y(yy) {this-> p1 = p1, this->p2 = p2; }
double getX(){ return x;}
double getY(){ return y;}
void setX(double xx)  {this->x = xx;}
void setY(double yy)  {this->y = yy;}
void setP1(smart_pointer <Point> p1) {this->p1 = p1;}
void setP2(smart_pointer <Point> p2) {this->p2 = p2;}
void print()
{
std::cout << "x= " << x << " y= " << y << '\n';
std::cout << "p1" << '\n';
if (p1 != NULL)
{
p1->print();
}
std::cout << "p2" << '\n';
if (p2 != NULL)
{
p2->print();
}
std::cout << '\n';
}
};

Liste de points 2D:

#include "Point.h"
class PointsList
{
private:
std::vector <smart_pointer <Point> > points;
public:
smart_pointer <Point> & operator [] ( int index ) {return points[index];}
public:
void push_back(smart_pointer <Point> p) {points.push_back(p);}
void erase(unsigned int index) {points.erase(points.begin() += index );}
void printPoints()
{
std::cout << "List of points" << '\n';
for (unsigned int i = 0; i < points.size();  i++)
{
points[i]->print();
}
}
};

Code de Test:

#include "Point.h"
#include "PointsList.h"
int main()
{
smart_pointer <Point> pb = NULL;
pb = (new Point(0,0));
smart_pointer <Point> p0(new Point(0,0));
p0->print();
smart_pointer <Point> p1(new Point(10,10));
p1->print();
smart_pointer <Point> p2(new Point(20,20));
p2->print();
smart_pointer <Point> p3(new Point(30,30));
p3->print();
smart_pointer <Point> pa(p3);
p0->setP1(p2);
p0->setP2(p3);
p0->print();    
p0 = p1;
p0->print();
p0->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;
}

Où sont advanteges ou disadvanteges d'une telle solution? Que penser de l'utilisation de la vitesse pour une quantité énorme de données, casting, des problèmes avec l'héritage, etc. Merci pour votre aide.

J'avais une question de plus pour cet exemple: quel type de pointeur intelligent (partagée, portée) serait pour de telles structures de données les plus appropriés:

//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-> p1 = NULL; this->p2 = NULL;}
...

};

//Class  with cross references: topological model for Delaunay triangulation
class Edge
{
private:
Point2D * start;
Edge *next;
Edge *previous;
Edge *twin;
...
};

Merci pour votre aide...

  • Peut-on suppose que c'est juste un exercice pour vous aider à comprendre?
  • PS. Vous avez oublié le constructeur de copie.
  • Oui, c'est juste un exemple de cyclique références de test, mais dans l'avenir, je voudrais mettre en œuvre de tels pointeurs intelligents dans mon application.
  • La mise en œuvre de votre propre est une mauvaise idée. L'obtention d'un pointeur intelligent correcte est beaucoup plus difficile qu'il n'y paraît. Veuillez utiliser celui fourni par une revue par les pairs de la bibliothèque C++(C ++ 0x std::shared_ptr/ C++03 boost::shared_ptr ou std::tr1::shared_ptr), Il a fallu beaucoup de temps pour aplanir les bugs dans ces pointeurs intelligents, mais ils travaillent très bien maintenant.
  • Je n'ai même jamais remarqué que partagé les pointeurs sont une partie de la nouvelle norme C++0x ... existe-il des différences entre le C++0x std::shared_ptr et std::tr1::shared_ptr ?
InformationsquelleAutor Ian | 2010-08-31