共享智能指针(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计数器,更无法解决共享指针的多线程安全问题

 

智能指针share_ptrC++11标准库中的一种用于管理动态分配内存的智能指针。它能够自动管理资源,在不需要时释放内存,防止内存泄漏。然而,在实际代码中,我们常常会遇到相互引用的情况,即两个或多个对象之间产生循环引用,导致内存泄漏。这种情况对于传统的裸指针来说是无法解决的,但对于智能指针share_ptr来说,则可以通过以下方法解决: 1.使用weak_ptr:在循环引用的情况下,一个对象可以通过weak_ptr共享相应的资源,而不会增加资源的引用计数。因此,在处理相互引用问题时,可以使用weak_ptr来打破循环引用,避免内存泄漏。 2.使用单独的管理对象:在某些情况下,多个对象之间的相互引用较为复杂,使用weak_ptr不能完全解决问题,例如多层嵌套的相互引用。这时候,可以引入一个额外的管理对象,用于管理这些对象之间的关系,从而减少相互引用的复杂度。 3.使用裸指针代替智能指针:虽然智能指针share_ptr可以很好地管理内存,但在某些场景下,使用裸指针可能会更为简单、清晰。例如,在处理循环引用时,可以使用裸指针进行判断,然后手动删除内存。 综上所述,智能指针share_ptrC++中非常有用的工具,在避免内存泄漏方面发挥了很大的作用。虽然在处理相互引用时可能会遇到一些麻烦,但使用上述方法可以很好地解决问题,保证代码质量和性能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值