码迷,mamicode.com
首页 > 编程语言 > 详细

C++智能指针的实现

时间:2015-07-02 10:11:27      阅读:130      评论:0      收藏:0      [点我收藏+]

标签: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前打印出所有析构函数的输出。


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

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

版权声明:本文为博主原创文章,未经博主允许不得转载。

C++智能指针的实现

标签:c++   智能指针   多线程   

原文地址:http://blog.csdn.net/u010125463/article/details/46719007

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!