C++ — 智能指針一

RAII

資源獲得及初始化,獲得資源馬上進行初始化
是一種利用對象生命週期來控制程序資源(如內存、文件句 柄、網絡連接、互斥量等等)的簡單技術。
在對象構造時獲取資源,接着控制對資源的訪問使之在對象的生命週期內始終保持有效,最後在對象析構的時候釋放資源。藉此,我們實際上把管理一份資源的責任託管給了一個對象。

//智能指針專門用來管理動態開闢的空間
//RAII不等價於只能指針
//RAII是解決問題的思想
//智能指針是RAII思想的一種實現
template<class T>
class SmartPtr
{
public:
	SmartPtr(T* ptr)	//在構造函數時保存動態開闢空間的指針
		:_ptr(ptr)
	{
	}
	~SmartPtr()	//在析構函數中釋放
	{
		delete _ptr;
	}
    T* get()
    {
        return _ptr;
    }
    T* operator*() 
    {
         return *_ptr;
    }
     T*   operator->()    
    {
         return _ptr;
    }
private:
	T* _ptr;
};
//託管
SmartPtr<int*> sp(new int);   //這樣在外界無法訪問,需要重載 operator*() operator->()
//這樣,就算拋異常導致結束時未釋放資源,函數結束銷燬對象時會自動調用析構函數

auto_ptr

//模仿實現
template<class T>
class auto_ptr   //C++98
{
public:
    auto_ptr(T* ptr)	//在構造函數時保存動態開闢空間的指針
		:_ptr(ptr)
	{
	}
	~auto_ptr()	//在析構函數中釋放
	{
		delete _ptr;
	}
     T* operator*() 
    {
         return *_ptr;
    }
     T* operator->()    
    {
         return _ptr;
    }
    
    //管理權轉移
    auto_ptr(const auto_ptr<T>& ap)
         :_ptr(ap._ptr)  // 這樣就解決了一塊空間被多個對象使用而造成程序奔潰問題
    {
        ap._ptr = nullptr;    //把兩個對象中的指針變爲一個
    }
    auto_ptr<T>& operator=(const auto_ptr<T>& ap)
    {
        if(this != &ap) // 檢測是否爲自己給自己賦值
        {
            if(_ptr) // 釋放當前對象中資源
            {
                delete _ptr;    //放置在賦值時這個對象本身就指向空間,賦值時而忘記釋放
            }
            _ptr = ap._ptr;  // 轉移資源到當前對象中
            ap._ptr = nullptr;
        }
        return *this;
    }
     //測試函數     
    void test_auto_ptr()
    {
        auto_ptr<int> ap1(new int);
        auto_ptr<int> ap2(ap1);        //不定義拷貝構造則淺拷貝,釋放兩次
       *ap1 = 10; //報錯    訪問空指針
        ap1 = ap3;    
    }
private:
    T* _ptr;
};

void test_auto_ptr()   
{
    //庫中的auto_pr
    std::auto_ptr<int> ap1(new int);
    std::auto_ptr<int> ap2(ap1);,//多次釋放
    *ap1 = 10; //崩潰, ap1已經成爲nullptr
}

unique_ptr

//推薦使用
//簡單粗暴,不允許拷貝
//是線程安全的,訪問數據需要加鎖,不會出現同時多線程使用
template<class T>
class unique_ptr
{
public:
    unique_ptr(T* ptr)	//在構造函數時保存動態開闢空間的指針
		:_ptr(ptr)
	{
	}
	~unique_ptr()	//在析構函數中釋放
	{
		delete _ptr;
	}
     T* operator*() 
    {
         return *_ptr;
    }
     T* operator->()    
    {
         return _ptr;
    }
    //不允許拷貝和賦值
    //// C++98防拷貝的方式:只聲明不實現+聲明成私有
    // C++11防拷貝的方式:delete
    unique_ptr(const unique_ptr<T>& up) = delete;
    unique_ptr<T>& operator=(const unique_ptr<T>& up) = delete;
    //測試函數  
    void test_unique_ptr()    //自己實現
	{
    	std::unique_ptr<int> ap1(new int);
    	std::unique_ptr<int> ap2(ap1);        //報錯,不能實現
	}
private:
        T* _ptr;
};

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章