强智能指针shared_ptr:
把管理的内存块的地址和有多少个指针指向封装成一个结构体(引用计数管理器(数组)),放在一个单独的类中。
接口:addRef()、delRef()、 getRef();
只需有一个管理器存在即可:适合使用单例模式:创建静态成员(为了线程安全应在类外先进行创建)
addRef():
1、地址没有记录:添加结点,引用计数置为1
2、地址已经记录:引用计数+1
delRef():
1、地址没有记录:抛出异常
2、地址记录:减引用计数
普通模式:
#include<iostream>
using namespace std;
class RefManage
{
public:
RefManage():length(0){}
void addRef(void* ptr)
{
if(ptr != NULL)
{
int index = find(ptr);
if(index < 0)
{
arr[length].addr = ptr;
arr[length++].refcount = 1;
}
else arr[index].refcount++;
}
}
void delRef(void* ptr)
{
int index = find(ptr);
if(index < 0)
{
throw exception("addr is not exist");
}
else
{
if(getRef(ptr) != 0)
{
arr[index].refcount--;
}
else
throw exception("refcount is 0");
}
}
int getRef(void* ptr)
{
if(ptr == NULL) return 0;
int index = find(ptr);
if(index < 0)
{
return -1;
}
else
{
return arr[index].refcount;
}
}
private:
int find(void* ptr)
{
for(int i = 0;i < length;i++)
{
if(arr[i].addr == ptr)return i;
}
return -1;
}
class Node
{
public:
Node(void* ptr = NULL,int ref = 0):addr(ptr),refcount(ref){}
public:
void* addr;
int refcount;
};
Node arr[10];
int length;//数组元素的有效长度 当前可以插入的数组下标
};
template<class T>
class Shared_ptr
{
public:
Shared_ptr(T* ptr):mptr(ptr)
{
AddRef();
}
Shared_ptr(const Shared_ptr<T>& rhs):mptr(rhs.mptr)
{
AddRef();
}
Shared_ptr<T>& operator=(const Shared_ptr<T>& rhs)
{
if(this != &rhs)
{
DelRef();
if(!GetRef())
{
delete mptr;
}
mptr = rhs.mptr;
AddRef();
}
return *this;
}
~Shared_ptr()
{
DelRef();
if(!GetRef())
{
delete mptr;
}
mptr = NULL;
}
T& operator*()
{
return *mptr;
}
T* operator->()
{
return mptr;
}
private:
void AddRef()
{
rm->addRef(mptr);
}
void DelRef()
{
rm->delRef(mptr);
}
int GetRef()
{
return rm->getRef(mptr);
}
private:
T* mptr;
static RefManage* rm;
};
template<class T>
RefManage* Shared_ptr<T>::rm = new RefManage;
int main()
{
int*p = new int;
Shared_ptr<int> sp1(p);
Shared_ptr<int> sp2(p);
Shared_ptr<int> sp3(p);
Shared_ptr<int> sp4(p);
return 0;
}
线程安全的单例模式:
#include<iostream>
using namespace std;
class RefManage
{
public:
static RefManage* getInstance()//通过此接口来创建对象,返回值不能直接用类类型,不然会生成临时对象
{
return &rm;//在main函数前就将对象生成好,在分线程时没有进程的创建,只需要返回已存在对象的地址,所以没有线程安全的问题
}
private:
static RefManage rm;//静态的成员对象属于类作用域下:优点:可以看到类中所有的东西(包括私有的),相当于把对象的生成放再类中;
//一定要在类外初始化,而对象生成就在初始化的时候,因为是全局变量,所以是放在.data段,
private:
RefManage():length(0){}//屏蔽构造函数和拷贝构造函数
RefManage(const RefManage& rhs);//用不上,所以只要声明,不用实现;原因:只有一个对象,不可能再去拷贝
public:
void addRef(void* ptr)
{
if(ptr != NULL)
{
int index = find(ptr);
if(index < 0)
{
arr[length].addr = ptr;
arr[length++].refcount = 1;
}
else arr[index].refcount++;
}
}
void delRef(void* ptr)
{
int index = find(ptr);
if(index < 0)
{
throw exception("addr is not exist");
}
else
{
if(getRef(ptr) != 0)
{
arr[index].refcount--;
}
else
throw exception("refcount is 0");
}
}
int getRef(void* ptr)
{
if(ptr == NULL) return 0;
int index = find(ptr);
if(index < 0)
{
return -1;
}
else
{
return arr[index].refcount;
}
}
private:
int find(void* ptr)
{
for(int i = 0;i < length;i++)
{
if(arr[i].addr == ptr)return i;
}
return -1;
}
class Node
{
public:
Node(void* ptr = NULL,int ref = 0):addr(ptr),refcount(ref){}
public:
void* addr;
int refcount;
};
Node arr[10];
int length;//数组元素的有效长度 当前可以插入的数组下标
};
RefManage RefManage::rm;
template<class T>
class Shared_ptr
{
public:
Shared_ptr(T* ptr):mptr(ptr)
{
AddRef();
}
Shared_ptr(const Shared_ptr<T>& rhs):mptr(rhs.mptr)
{
AddRef();
}
Shared_ptr<T>& operator=(const Shared_ptr<T>& rhs)
{
if(this != &rhs)
{
DelRef();
if(!GetRef())
{
delete mptr;
}
mptr = rhs.mptr;
AddRef();
}
return *this;
}
~Shared_ptr()
{
DelRef();
if(!GetRef())
{
delete mptr;
}
mptr = NULL;
}
T& operator*()
{
return *mptr;
}
T* operator->()
{
return mptr;
}
private:
void AddRef()
{
rm->addRef(mptr);
}
void DelRef()
{
rm->delRef(mptr);
}
int GetRef()
{
return rm->getRef(mptr);
}
private:
T* mptr;
static RefManage* rm;
};
template<class T>
RefManage* Shared_ptr<T>::rm = new RefManage::getInstance();
int main()
{
int*p = new int;
Shared_ptr<int> sp1(p);
Shared_ptr<int> sp2(p);
Shared_ptr<int> sp3(p);
Shared_ptr<int> sp4(p);
return 0;
}
Shared_ptr所存在的问题:
代码如下:
class B;
class A
{
public:
A()
{
cout<<"A::A()"<<endl;
}
~A()
{
cout<<"A::~A()"<<endl;
}
public:
Shared_ptr<B> pa;
};
class B
{
public:
B()
{
cout<<"B::B()"<<endl;
}
~B()
{
cout<<"B::~B()"<<endl;
}
public:
Shared_ptr<A> pb;
};
int main()
{
Shared_ptr<A> spa(new A());
Shared_ptr<B> spb(new B());
spa->pa = spb;
spb->pb = spa;
return 0;
}