Simple reference counting: smart pointers(简单引用计数:智能指针)
本文介绍了简单引用计数:智能指针的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
我想使用智能指针实现一个简单的引用计数。变量pointer
表示指向存储对象的指针,reference_count
表示对象副本的总数。
- 如果我们使用NULL初始化对象:Reference_count=-1否则Reference_Count=1
- COPY CTOR AND OPERATOR=INCREMENT REFERENCE_COUNT
- 析构函数递减Reference_count,如果没有对指定对象的其他引用,则执行其删除。
以下是我的代码:
#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: " << '
';
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;
}
};
这是我的测试代码,类示例存储2D点和指向任何其他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 << '
';
std::cout << "p1" << '
';
if (p1 != NULL)
{
p1->print();
}
std::cout << "p2" << '
';
if (p2 != NULL)
{
p2->print();
}
std::cout << '
';
}
};
二维点列表:
#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" << '
';
for (unsigned int i = 0; i < points.size(); i++)
{
points[i]->print();
}
}
};
测试代码:
#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;
}
这种解决方案的优点或缺点在哪里?海量数据、强制转换、可能的继承问题等的运行速度如何?谢谢您的帮助。
我对此示例还有一个问题:哪种类型的智能指针(共享的、作用域的)最适合这样的数据结构:
//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;
...
};
感谢您的帮助...
推荐答案
您的引用计数不起作用。
如果将两个智能指针一起复制或赋值,则它们需要使用相同的位置执行计数。
当前每个对象都保留自己的计数,因此它们可能不同步。
smart_pointer<int> x(new x); // x.pointer: <good> x.reference_count: 1
{
smart_pointer<int> y; // y.pointer: NULL y.reference_count: -1
y = x; // x.pointer: <good> x.reference_count: 1
// y.pointer: <good> y.reference_count: 2
smart_pointer<int> z;
x = z; // x.pointer: NULL x.reference_count: 0 (BAD)
// z.pointer: NULL z.reference_count: -1
// y.pointer: <bad> (it was deleted by x) y.reference_count: 2
}
编辑:
按照注释中的要求说明问题。
在那个点上。其中我们刚刚创建了z。但尚未完成x = z;
x { pointer: 0xabcd1234 reference_count: 1 }
y { pointer: 0xabcd1234 reference_count: 2 }
z { pointer: NULL reference_count: -1 }
// So here is your assignment operator.
// Doing the `x = z` we will walk through the following code.
//
smart_pointer <T> & operator = (const smart_pointer <T> & p)
{
if (this != &p)
{
// We get here.
// Left hand side is 'x' so this condition will be true.
if( -- reference_count == 0)
{
// Now we are deleting a pointer.
// That is held by 'x'
delete pointer;
// But 'y' is holding a pointer with the same value.
// Now y is holding a pointer to a deleted variable.
}
// Here we copy 'z' into 'x'
// Copy the pointer. That happens to be NULL.
pointer = p.pointer;
// Now we copy and increment the reference count.
// So 'x' has a value of 0 while 'z' has a value of -1.
// This also breaks the invariant on 'x' that NULL values should
// have a reference count of -1 (as X is NULL and ref-count is 0)
reference_count = p.reference_count + 1;
}
return *this;
}
如果任何人尝试使用‘y’,我们现在有未定义的行为,因为它包含指向已释放的内存的指针。
编辑经典(但过于简单的智能指针:
#include <vector>
template<typename T>
class SP
{
T* object;
size_t* count;
public:
SP(T* data)
try
// Use weird try around initializer list to catch new throwing.
// If it does we delete data to stop it from leaking.
:object(data)
,count(data ? new int(1) : NULL)
{ /* This is the constructor *
沃梦达教程
本文标题为:简单引用计数:智能指针
猜你喜欢
- XML Schema 到 C++ 类 2022-01-01
- OpenGL 对象的 RAII 包装器 2021-01-01
- 将函数的返回值分配给引用 C++? 2022-01-01
- 将 hdc 内容复制到位图 2022-09-04
- 从父 CMakeLists.txt 覆盖 CMake 中的默认选项(...)值 2021-01-01
- DoEvents 等效于 C++? 2021-01-01
- 使用 __stdcall & 调用 DLLVS2013 中的 GetProcAddress() 2021-01-01
- GDB 不显示函数名 2022-01-01
- 如何提取 __VA_ARGS__? 2022-01-01
- 哪个更快:if (bool) 或 if(int)? 2022-01-01