【C++】スマートポインタshared_ptr位置決め削除器(シミュレーション関数)


スマートポインタshared_ptrは参照カウントで実現するのはよさそうですが、問題があります.
1、参照カウントの更新にはスレッドセキュリティが存在する.
2、循環参照--弱い参照インテリジェントポインタ(weak_ptr)を使用して循環参照を破る(weak_ptrは参照カウントを増加しない)
3、定置削除器と空間分配器
たとえば、ファイルのクローズを開き、mallocで開いたスペースを参照カウントで実現すると問題が発生します.
リファレンスカウントを変更するときにロックをかけると、リファレンスカウントの更新にスレッドセキュリティが存在することを解決できます.
循環参照の問題
#include<iostream>
using namespace std;
#include<memory>//    shared_ptr
struct ListNode
{
	shared_ptr<ListNode> _prev;
	shared_ptr<ListNode> _next;
	~ListNode()
	{
		cout << "~ListNode()" << endl;
	}
};

void  Test2()
{
	shared_ptr<ListNode> cur(new ListNode);//1
	shared_ptr<ListNode> next(new ListNode);//2
	cout << "cur->" << cur.use_count() << endl;//use_count  shared_ptr     
	cout << "next->" << next.use_count() << endl;

	cur->_next = next;//3
	next->_prev = cur;//4
	cout << "cur->" << cur.use_count() << endl;
	cout << "next->" << next.use_count() << endl;
}
//    1、2  cur next      1,    1、2      2。
//             ,  cur        next  , next       cur   ,          。
//weak_ptr(       )                  。
struct ListNode
{
    weak_ptr<ListNode> _prev;
    weak_ptr<ListNode> _next;
    ~ListNode()
    {
        cout << "~ListNode()" << endl;
    }
};

プリセット削除器とスペース割り当て器(ps:スペース割り当て器のプリセット特殊シーンでのみ使用)
ポインタがファイルタイプを指す場合、空間を解放するのではなく、構造関数でファイルを閉じるだけです.空間がmallocによって開かれている場合は、deleteオペレータではなく、構造関数でfree関数を呼び出します.上記の問題はシミュレーション関数によって解決できる.具体的なコードは以下の通りです.
template<class T>
class Del
{
public:
	void operator() (const T *ptr)
	{
		delete ptr;
	}
};
//     FClose Free
struct FClose
{
	void operator() (void* ptr)
	{
		cout << "Close" << endl;
		fclose((FILE*)ptr);
	}
};
struct Free
{
	void operator() (void* ptr)
	{
		cout << "Free" << endl;
		free(ptr);
	}
};

template<class T,class Deleter=Del<T>>
class SharedPtr
{
public:
	SharedPtr(T* ptr)
		:_ptr(ptr)
		, _pCount(new long(1))
	{}
	SharedPtr(T* ptr,Deleter del)
		:_ptr(ptr)
		, _pCount(new long(1))
		, _del(del)
	{}
	SharedPtr<T>& operator=(SharedPtr<T> sp)
	{
		swap(_ptr, sp._ptr);
		swap(_pCount, sp._pCount);
		return *this;
	}
	~SharedPtr()
	{
		cout << "~SharedPtr()" << endl;
		Release();
	}
	T& operator*()
	{
		return *_ptr;
	}
	T* GetPtr()//     _ptr
	{
		return  _ptr;
	}
	T* operator->()
	{
		return _ptr;
	}
	void Release()//    
	{
		if (--(*_pCount) == 0)
		{
			_del(_ptr);
			delete _pCount;
		}
	}
private:
	T* _ptr;
	long* _pCount;
	Deleter _del;
};

void Test3()
{
	//         
	SharedPtr<int> sp(new int(6));
	SharedPtr<FILE, FClose> sp1(fopen("test.text", "w"), FClose());
	SharedPtr<int, Free> sp2((int*)malloc(sizeof(int)* 6), Free());
}