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 ?
Vous devez vous connecter pour publier un commentaire.
Votre comptage de référence ne fonctionne pas.
Si vous copiez ou assigner deux pointeurs intelligents ensemble, ils doivent utiliser le même emplacement pour effectuer le comptage.
Actuellement, chaque objet garde sa propre décompte et ils peuvent donc devenir de la synchronisation.
Edit:
Illustrer le problème comme l'a demandé dans les commentaires.
Au point. Où nous venons de créer z. Mais pas encore fait
x = z;
Si quelqu'un essaie d'utiliser " y " maintenant, nous avons un comportement indéfini, car il contient un pointeur vers la mémoire qui a été allouée.
Édition Classique (mais un peu trop simpliste pointeur intelligent:
count(new int(1))
j'ai juste essayé d'augmenter le comte, qui fait référence à null. je me demandais comment faire. Mais oui, merci beaucoup pour le new int(1) conseil 🙂new int(1)
devrait êtrenew size_t(1)
et je pense que vous devriez renvoyer après le supprimer dans le même constructeur.Je suis sûr que vous avez fait un excellent travail, mais pourquoi ne pas utiliser le pointeur intelligent disponible en boost ou loki? Les deux sont le produit de nombreuses années de raffinement.