• C++智能指针的实现


    说起智能指针,不少人都不陌生。比方auto_ptr、shared_ptr、unique_ptr、weak_ptr。

    依据shared_ptr的功能,自己仿造也实现了个。


    对于shared_ptr这样的智能指针,有一个共享的引用计数器来控制指针对象的销毁,当引用计数器变为0时。则销毁指针指向的对象。对于多线程安全问题,我在代码中使用的Interlocked系列的原子操作函数。


    在学习过程中,渐渐学会了RAII(Resource Acquisition Is Initialization),慢慢领略到了这样的模式的优点。

    直接上代码:

    SmartPtr.hpp

    #pragma once
    #include "stdafx.h"
    #include <assert.h>
    #include <windows.h>
    
    //#define DEBUG_SMARTPTR
    
    template<typename T>
    class SmartPtr;
    
    template <typename T>
    class RefPtr
    {
    	friend class SmartPtr<T>;
    	explicit RefPtr(T *p) :pointer(p), nUse(0)
    	{	
    		assert(pointer);
    #ifdef DEBUG_SMARTPTR
    		std::cout << "Create Pointer!" << std::endl;
    #endif
    	}
    
    	RefPtr(const RefPtr&)
    	{
    
    	}
    
    	RefPtr& operator= (const RefPtr & ref)
    	{
    
    	}
    
    	~RefPtr()
    	{
    #ifdef DEBUG_SMARTPTR
    		std::cout << "Delete Pointer!" << std::endl;
    #endif
    		assert(pointer);
    		if (pointer != NULL)
    		{
    			delete pointer;
    			pointer = NULL;
    		}	
    	}
    
    	unsigned int AddRefCount()
    	{
    		return InterlockedIncrement((unsigned int*)&nUse);
    	}
    
    	unsigned int SubRefCount()
    	{
    		return InterlockedDecrement((unsigned int*)&nUse);
    	}
    
    	bool AddRefCount_lock()
    	{
    		for (;;)
    		{
    			unsigned int temp = nUse;
    			if (temp == 0)
    			{
    				return false;
    			}
    			if (InterlockedCompareExchange((unsigned int *)&nUse, temp + 1, temp) == temp)
    			{
    				return true;
    			}
    		}		
    	}
    
    	volatile unsigned int nUse;
    	T *pointer;
    };
    
    template<typename T>
    class SmartPtr
    {
    public:
    	explicit SmartPtr(T *pointer) :ptr(new RefPtr<T>(pointer))
    	{
    		assert(pointer);
    #ifdef DEBUG_SMARTPTR
    		std::cout << "Create SmartPointer!" << std::endl;
    #endif
    		ptr->AddRefCount();
    	}
    
    	explicit SmartPtr(const SmartPtr<T>& sp) :ptr(sp.ptr)
    	{
    #ifdef DEBUG_SMARTPTR
    		std::cout << "Copy0 SmartPointer!" << std::endl;
    #endif
    		ptr->AddRefCount();
    	}
    
    	explicit SmartPtr(const SmartPtr<T>* sp) :ptr(sp->ptr)
    	{
    #ifdef DEBUG_SMARTPTR
    		std::cout << "Copy1 SmartPointer!" << std::endl;
    #endif
    		ptr->AddRefCount();
    	}
    
    	SmartPtr& operator=(const SmartPtr<T>& sp)
    	{
    		if (sp.ptr != ptr)
    		{
    			//注意先加后减,防止指向同对象析构的问题
    			if (sp.ptr->AddRefCount_lock())
    			{
    				if (ptr->SubRefCount() == 0)
    				{
    					delete ptr;
    				}
    				ptr = sp.ptr;
    			}
    		}
    #ifdef DEBUG_SMARTPTR
    		std::cout << "Copy2 SmartPointer!" << std::endl;
    #endif
    		return *this;
    	}
    
    	T* operator->()
    	{
    		return GetPtr();
    	}
    
    	T* operator->() const
    	{
    		return GetPtr();
    	}
    
    	T& operator*()
    	{
    		return *ptr->pointer;
    	}
    
    	T& operator*() const
    	{
    		return *ptr->pointer;
    	}
    
    	bool operator!()
    	{
    		return !ptr;
    	}
    
    	~SmartPtr()
    	{
    		if (ptr->SubRefCount() == 0)
    		{
    			delete ptr;
    		}
    #ifdef DEBUG_SMARTPTR
    		std::cout << "Delete SmartPointer!" << std::endl;
    #endif
    	}
    
    	int GetRefCount() const
    	{
    		return ptr->nUse;
    	}
    
    	bool isNull()
    	{
    		return ptr->pointer == NULL;
    	}
    
    	T* GetPtr() const
    	{
    		assert(ptr->pointer);
    		return ptr->pointer;
    	}
    
    	//返回对象
    	T GetValue() const
    	{
    		assert(ptr->pointer);
    		return *ptr->pointer;
    	}
    
    private:
    	RefPtr<T> *ptr;
    };
    
    //兼容const比較
    template<typename T>
    inline bool operator==(const SmartPtr<T>& a,const SmartPtr<T>& b)
    {
    	return a.GetPtr() == b.GetPtr();
    }
    template<typename T>
    inline bool operator!=(const SmartPtr<T>& a,const SmartPtr<T>& b)
    {
    	return a.GetPtr() != b.GetPtr();
    }
    test.cpp

    #include "SmartPtr.hpp"
    #include <iostream>
    #include <process.h>
    
    
    #define THREADCOUNT 10
    
    typedef struct _PERSON_
    {
    	char szName[20];
    	int nAge;
    	~_PERSON_()
    	{
    		std::cout << "Person Distructor!"<< std::endl;
    	}
    }PERSON;
    
    SmartPtr<PERSON> g_p(new PERSON{ "g_test", 12 });
    
    unsigned int __stdcall testThread(void *pParam)
    {
    	SmartPtr<PERSON> sp((SmartPtr<PERSON> *)pParam);
    	g_p = sp;
    	std::cout << sp->nAge << std::endl;
    	return 0;
    }
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    	do 
    	{
    		HANDLE hThread[THREADCOUNT];
    		SmartPtr<PERSON> p0(new PERSON{ "Jovi", 12 });
    		SmartPtr<PERSON> p1(new PERSON{ "Solanin", 13 });
    
    		SmartPtr<PERSON> p2(p1);
    		const SmartPtr<PERSON> p3(p1);
    
    		SmartPtr<PERSON> p4(p3);
    		std::cout << (p3 == p1) << std::endl;
    		std::cout << (p2 == p0) << std::endl;
    		std::cout << (p3 != p1) << std::endl;
    		std::cout << (p2 != p0) << std::endl;
    		p4 = p0;
    		SmartPtr<PERSON> *p = new SmartPtr<PERSON>(p1);
    		for (int i = 0; i < THREADCOUNT; i++)
    		{
    			hThread[i] = (HANDLE)_beginthreadex(NULL, 0, testThread, (void *)p, 0, 0);
    //			WaitForSingleObject(hThread[i], INFINITE);
    		}
    		WaitForMultipleObjects(THREADCOUNT, hThread, TRUE, INFINITE);
    		delete p;
    	} while (0);
    
    	system("pause");
    	return 0;
    }
    
    此处的do while(0)仅仅是我想在pause前打印出全部析构函数的输出。


    对于基于引用计数器的智能指针,最致命缺点就是循环引用,导致对象被长期占用,无法释放。

    以上是我对智能指针的实现和个人看法,如有不对的地方,欢迎指出。

  • 相关阅读:
    docker save docker load
    Vue 开发线路 资料 汇总
    electron 开发拆坑总结
    mysqldbcopy 数据库复制工具
    用rsync命令删除大文件夹
    linux nc,nmap,telnet ,natstat命令
    搭建云版容器版本 需要的基础软件 安装工具
    phantomjs 前端测试工具
    消息列队 php 基于redis 实现
    部分安卓机器【小米手机】,文字显示不全
  • 原文地址:https://www.cnblogs.com/mfrbuaa/p/5157999.html
Copyright © 2020-2023  润新知