共享智能指针(SharePtr)的C++实现

 

C++ 共享智能指针实现(支持多线程安全)

主要实现思想是引用计数法,在SharePtr类拷贝(Copy)和赋值(=)的时候引用计数加1,而在SharePtr类变量析构的时候引用计数减少1

实现细节

(1)SharePtr包裹类变量指针和引用计数指针int*, 这里引用计数采用 int* 为了在各个SharePtr变量实现计数共享,每个变量的计数变化都会影响其他计数

 

enum EThreadType
{
	SingleThread,
	MultiThread,
};


template<typename ObjectType, EThreadType ThreadType = EThreadType::SingleThread>
class SharePtr
{
private:
	ObjectType* objectPtr = nullptr;
	int* count = nullptr;;
	mutex threadMutex;

 

(2) 拷贝构造和赋值引用计数加1

	//拷贝构造,相当于SharePtr<ObjectType>(const SharePtr<ObjectType>& other)
	SharePtr(const SharePtr& other)
	{
		Assignment(other);
	}

	//赋值构造
	SharePtr& operator=(const SharePtr& other)
	{
		Assignment(other);
		return *this;
	}

    void Assignment(const SharePtr<ObjectType, ThreadType>& other)
	{
		Decrease();
		count = other.count;
		objectPtr = other.objectPtr;

		if (EThreadType::MultiThread == ThreadType)
			threadMutex.lock();

		if (count != nullptr)
		{
			(*count)++;
		}

		if (EThreadType::MultiThread == ThreadType)
			threadMutex.unlock();
	}

 

(3)析构引用计数减少1,当减少为0,则析构共享指针保存的对象的内存

	void Decrease()
	{
		if (EThreadType::MultiThread == ThreadType)
			threadMutex.lock();

		if (nullptr != count)
		{
			(*count) -= 1;
			if (*count == 0)
			{
				if (nullptr != objectPtr)
				{
					delete objectPtr;
					objectPtr = nullptr;
				}
				delete count;
				count = nullptr;
			}
		}

		if (EThreadType::MultiThread == ThreadType)
			threadMutex.unlock();
	}


  ~SharePtr()
  {
 	 Decrease();
  }

 

(4)共享指针SharePtr总体实现,设计了MakeShared模板函数实现了不定形参,支持模板类对象的构造函数不定形参,和C++ STL的make_shared具备相同的效果

enum EThreadType
{
	SingleThread,
	MultiThread,
};


template<typename ObjectType, EThreadType ThreadType = EThreadType::SingleThread>
class SharePtr
{
private:
	ObjectType* objectPtr = nullptr;
	int* count = nullptr;;
	mutex threadMutex;

public:
	SharePtr()
	{

	}

	//拷贝构造,相当于SharePtr<ObjectType>(const SharePtr<ObjectType>& other)
	SharePtr(const SharePtr& other)
	{
		Assignment(other);
	}

	//赋值构造
	SharePtr& operator=(const SharePtr& other)
	{
		Assignment(other);
		return *this;
	}


	ObjectType* operator->()
	{
		return objectPtr;
	}

	~SharePtr()
	{
		Decrease();
	}

private:

	void Assignment(const SharePtr<ObjectType, ThreadType>& other)
	{
		Decrease();
		count = other.count;
		objectPtr = other.objectPtr;

		if (EThreadType::MultiThread == ThreadType)
			threadMutex.lock();

		if (count != nullptr)
		{
			(*count)++;
		}

		if (EThreadType::MultiThread == ThreadType)
			threadMutex.unlock();
	}

	void Decrease()
	{
		if (EThreadType::MultiThread == ThreadType)
			threadMutex.lock();

		if (nullptr != count)
		{
			(*count) -= 1;
			if (*count == 0)
			{
				if (nullptr != objectPtr)
				{
					delete objectPtr;
					objectPtr = nullptr;
				}
				delete count;
				count = nullptr;
			}
		}

		if (EThreadType::MultiThread == ThreadType)
			threadMutex.unlock();
	}

public:
	template<typename...Args>
	void InitObject(Args&&...args)
	{
		if (nullptr != objectPtr)
		{
			delete objectPtr;
			objectPtr = nullptr;
		}

		if (nullptr != count)
		{
			delete count;
			count = nullptr;
		}

		objectPtr = new ObjectType(std::forward<Args>(args)...);
		count = new int;
		*count = 1;
	}

	template<typename ObjectType, EThreadType ThreadType,typename...Args>
	friend SharePtr<ObjectType, ThreadType> MakeShared(Args&&...args);
};



//发生拷贝构造在析构
template<typename ObjectType, EThreadType ThreadType = EThreadType::SingleThread, typename...Args>
SharePtr<ObjectType, ThreadType> MakeShared(Args&&...args)
{
	SharePtr<ObjectType, ThreadType> ObjectPtr;
	ObjectPtr.InitObject(std::forward<Args>(args)...);
	return ObjectPtr;
}

 

(5)SharePtr不提供直接New构造对象的函数,是考虑到智能指针的滥用,二次GC导致Delete空指针而程序崩溃, 仅仅开放出MakeShared接口来返回共享指针对象。 下面的用STL的共享指针shared_ptr滥用导致程序崩溃

class UObject
{
public:
	UObject(float inValue)
	{
		value = inValue;
		std::cout << "UObject Construct" << std::endl;
	}

	~UObject()
	{
		std::cout << "UObject Unonstruct" << std::endl;
	}

	float GetValue()
	{
		return value;
	}

private:
	float value;
};


void Func()
{
    UObject* a = new UObject(0.6666);
	shared_ptr<UObject> MyObjectPtr(a);
	shared_ptr<UObject> MyObjectPtr1(a);	
}

int main()
{
	Func();
	system("pause");
}

 

 

正确使用样例:

void Func()
{
	SharePtr<UObject> MyObjectPtr = MakeShared<UObject>(0.6666f);
	SharePtr<UObject> MyObjectPtr1 = MyObjectPtr;
	SharePtr<UObject> MyObjectPtr2;
	MyObjectPtr2 = MyObjectPtr1;
	std::cout << "value = " << MyObjectPtr2->GetValue() << std::endl;
}

int main()
{
	Func();
	system("pause");
}

 

 

(6)因为是玩具版共享指针,没有像STL的共享指针一样使用atomic计数器,更无法解决共享指针的多线程安全问题

 

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值