(二)智能指针----shared_ptr/weak_ptr

我们知道auto_ptr,unique_ptr构造或者析构后,都会将自身的管理权限转移,那么如何解决这个问题呢,boost库也给我们提供了带引用计数的指针。

1:shared_ptr

shared_ptr是最常用的智能指针,shared_ptr采用了引用计数器,多个shared_ptr中的T *ptr指向同一个内存区域(同一个对象),并共同维护同一个引用计数器。shared_ptr定义如下,记录同一个实例被引用的次数,当引用次数大于0时可用,等于0时释放内存。所以用户可以自由的赋值和构造,只要其引用计数不为0,对象所指的内存就不会被析构掉,也就不会产生错误。

在shared_ptr的操作中,我们对于动态内存的开辟及初始化最好是使用make_shared这个函数模板,而不是使用new,为什么呢?

同直接使用new相比,make函数减小了代码重复,提高了异常安全,并且对于std::make_shared和std::allcoated_shared,生成的代码会更小更快。

具体的new与make_shared的比较大家可以参考这个链接https://blog.csdn.net/coolmeme/article/details/43405155

我们来实现一个简单的shared_ptr(实现方法很多,我只列举一二)

//shared_ptr 引用计数用map表来表示的第一种实现方式
template<typename T>
class SharedPtr
{
public:
    SharedPtr(T *p=NULL):ptr(p)
    {
	mmap.insert(make_pair(ptr,1));  //将ptr及其引用计数插入map表中
    }
    SharedPtr(const SharedPtr & rt)  //拷贝构造函数
    {
	ptr=rt.ptr;    
	mmap[ptr]++;   //通过mmap[]里的键就可以访问到键所对应的值,将值增加
    }
    SharedPtr& operator=(const SharedPtr & rt)
    {
    	if(&rt!=this)     //判断自赋值
    	{
	    if(--mmap[ptr]<=0)  //如果被赋值的对象只有一个指向那块内存,就要讲内存释放,并且在map表中将数据擦去
	    {
	        if(ptr!=NULL)
	         {
	             delete ptr;   //释放内存
		     ptr=NULL;
		 }
	   mmap.erase(ptr);   //擦去map表中的数据
	    }
	    ptr=rt.ptr;
	    mmap[ptr]++;
	    return *this;
	}
    }
    T &operator *()
    {
	return *ptr;
    }
    T *operator->()
    {
	return ptr;
    }
    ~SharedPtr()
    {
       	if(--mmap[ptr]<=0)  //判断是否此对象是内存指向的最后一个对象
	{
	    if(ptr!=NULL)
	    {
		delete ptr;  //释放掉内存
		ptr=NULL;
	    }
	    mmap.erase(ptr);   //在map表中擦掉数据
	}
    }
private:
        static map<T *,int>mmap;   //同一个类共用一个map表
	T *ptr;
	
};
template<typename T>
map<T *,int> SharedPtr<T>::mmap; //map表有一个特性,不能插入键相同的数据,虽然插入不会出错,但是不会改变原先的键所对应的值,后插的是插不进去的

 未完。。。。

2:weak_ptr

猜你喜欢

转载自blog.csdn.net/Eunice_fan1207/article/details/83051919