一. 存在問題
上文到第三種智能指針shareptr,但是此指針也存在很多的問題
- 若傳入文件類型指針FILE *,則delete不能釋放;
- 引用計數的處理不是線程安全的
- 循環引用問題
二.解決方法
- 若傳入文件類型指針FILE *,則delete不能釋放;
- 解決方法:特化
class Fclose
{
public:
void operator()(FILE* fp)
{
if(fp)
fclose(fp);
}
};
template <class T>
class Delete
{
public:
void operator()(T*p)
{
if(p)
delete p;
}
}
template <class T>
class Free
{
public:
void operator()(T*p)
{
if(p)
free p;
}
}
template <class T,class Del= Delete<T>>
class SharePtr
{
//構造函數同上
//拷貝構造函數同上
SharedPtr<T>& operator=(SharedPtr<T> sp)
{
if(this!= &sp)
{
Release();
_ptr = sp._ptr;
_pCount = sp._pCount;
++(*_pCount);
}
return *this;
}
~SharedPtr()
{
cout << "~SharedPtr()" << endl;
Release();
}
private:
void Release()
{
if(_ptr && 0==--(*pCount))
{
Del()(_ptr);
_ptr = NULL;
delete _pCount;
_pCount = NULL;
}
}
};
- 引用計數的處理不是線程安全的
#include<memory>
template<class T>
struct Node
{
Node(const T&data)
:_next(NULL)
,_pre(NULL)
,_data(data)
{
cout<<"Node()"<<endl;
}
~Node()
{
cout<<"~Node()"<<endl;
}
share_ptr<Node<T>> _next;//以前_next交給一個原生態指針管理,現在交給share_ptr管理
share_ptr<Node<T>> _ptr;
T _data;
};
void Test()
{
share_ptr<Node<T>> p1(new Node<int>(1));
share_ptr<Node<T>> p2(new Node<int>(1));
cout<<p1.use_count()<<endl;
cout<<p2.use_count()<<endl;
p1->_next = p2;
p2->_pre = p1;
cout<<p1.use_count()<<endl;
cout<<p2.use_count()<<endl;
}
打印結果爲
Node()
Node()
1
1
2
2
問題
以上打印結果可知,並沒有調用析構函數,故會造成內存泄漏
循環引用:針對那些兩個指針的節點,可以引發引用循環的問題
- 循環引用問題
struct Node
{
Node(const T&data)
:_data(data)
{}
weak_ptr<Node<T>> _next;//weak_ptr依附於share_ptr,不能單獨使用;
weak_ptr<Node<T>> _pre;
}