shared_ptr实现机制

一、概述

shared_ptr实现了引用计数的功能,在引用计数为0时,自动delete掉管理的对象。

二、实现要点

  • shared_ptr需要实现构造对象以及赋值时的计数。
  • shared_ptr需要实现自身销毁时的计数减少。
  • 需要实现计数为0时自动销毁管理的对象。
  • 需要实现std::move语义。
  • 要处理多线程下的计数问题。

三、shared_ptr的简单实现源码

#pragma once
#include <memory>
#include <atomic>
using namespace std;
template<class T> class MyRefCount
{
    
    
private:
	atomic<long> _uses; //atomic使用CPU级的控制,保证多个线程,一个在修改时,其他线程查看和修改回退。
	T* _ptr;
	//long weaks; 这个用来处理weak_ptr,本代码不做实现
	void destory()
	{
    
    
		delete _ptr; //计数为0后,调用实际对象的析构函数
	}
public:
	MyRefCount(T* ptr)
	{
    
    
		_ptr = ptr;
		_uses = 1;
	}
	void incRef()
	{
    
    
		_uses++;
		
	}

	void decRef()
	{
    
    
		_uses--;
		if (_uses == 0)
		{
    
    
			destory();
		}
	}
	long use_count()
	{
    
    
		return _uses;
	}
};
template<class T> class MySharedPtr
{
    
    
private:
	T* _ptr;
	MyRefCount<T>* _refCount;
public:
	MySharedPtr()
	{
    
    
		_ptr = nullptr;
		_refCount = nullptr;
	}
	MySharedPtr(T* ptr)
	{
    
    
		this->_ptr = ptr;
		_refCount = new MyRefCount<T>(ptr);
	}
	~MySharedPtr()
	{
    
    
		if (_refCount != nullptr)
		{
    
    
			_refCount->decRef();
			_refCount = nullptr;
		}
		_ptr = nullptr;
	}
	MySharedPtr(const MySharedPtr<T>& right) //拷贝构造函数
	{
    
    
		if (right._refCount != nullptr)
		{
    
    
			right._refCount->incRef(); //右值被引用次数加1
		}
		_ptr = right._ptr; //左值用右值的ptr
		_refCount = right._refCount; //左值用右值的refcount
	}
	MySharedPtr(MySharedPtr<T>&& right) //移动构造函数
	{
    
    
		//把右值的归属权转移给左值
		_ptr = right._ptr;
		_refCount = right._refCount;

		right._ptr = nullptr;
		right._refCount = nullptr;

	}
	MySharedPtr<T>& operator=(MySharedPtr<T>& right)
	{
    
    
		right._refCount->incRef();
				
		if (_refCount != nullptr)
		{
    
    
			_refCount->decRef();
		}
		_ptr = right._ptr;
		_refCount = right._refCount;
		return (*this);
	}
	MySharedPtr<T>& operator=(MySharedPtr<T>&& right)
	{
    
    
		MySharedPtr<T> t = std::move(right); //= std::move 会调用移动构造函数,t获得right的数据所有权,right失去数据所有权
		t.swap(*this); //交换t和this,然后t在函数退出时清理掉,会让原本this指向的对象计数减1
		return (*this);
	}
	void swap(MySharedPtr<T>& t)
	{
    
    
		std::swap(this->_refCount, t._refCount);
		std::swap(this->_ptr, t._ptr);
	}

	T* get() //获取原生指针
	{
    
    
		return _ptr;
	}
	T* operator->() //重载指针操作符,实现用MySharedPtr访问T的成员
	{
    
    
		return get();
	}
	
	long use_count() //返回引用的数量
	{
    
    
		return _refCount != nullptr?_refCount->use_count():0;
	}

};
class MySharedPtrClass
{
    
    
public:
	int v;
	~MySharedPtrClass()
	{
    
    
		printf("MySharedPtrClass destory\n");
	}
};
class MySharedPtrTest
{
    
    
private:
	void func(MySharedPtr<MySharedPtrClass> mySharedPtr, shared_ptr<MySharedPtrClass> sharedPtr)
	{
    
    
		printf("mySharedPtr use count=%ld, sharedPtr use count=%ld\n", mySharedPtr.use_count(), sharedPtr.use_count());
		mySharedPtr->v = 1;
	}
public:
	
	void doTest()
	{
    
    
		MySharedPtr<MySharedPtrClass> mySharedPtr(new MySharedPtrClass());
		shared_ptr<MySharedPtrClass> sharedPtr(new MySharedPtrClass());

		printf("mySharedPtr use count=%ld, sharedPtr use count=%ld\n", mySharedPtr.use_count(),sharedPtr.use_count());
		MySharedPtr<MySharedPtrClass> myT = mySharedPtr;
		shared_ptr<MySharedPtrClass> t = sharedPtr;
		printf("mySharedPtr use count=%ld, sharedPtr use count=%ld\n", mySharedPtr.use_count(), sharedPtr.use_count());

		func(mySharedPtr, sharedPtr);
		printf("mySharedPtr use count=%ld, sharedPtr use count=%ld\n", mySharedPtr.use_count(), sharedPtr.use_count());

		myT = std::move(mySharedPtr);
		t = std::move(sharedPtr);
		printf("mySharedPtr use count=%ld, sharedPtr use count=%ld\n", mySharedPtr.use_count(), sharedPtr.use_count());

	}
	
};

猜你喜欢

转载自blog.csdn.net/gamekit/article/details/107194984
今日推荐