智能指針(續)

一. 存在問題

上文到第三種智能指針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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章