智慧指標之 Auto_Ptr
在介紹智慧指標之前我們先看以下程式碼:
void FunTest()
{
int *p = new int[10];
FILE* pFile = fopen( "1.txt", "w" );
if (pFile == NULL)
{
return;
}
// DoSomethint();
if (p != NULL)
{
delete[] p;
p = NULL;
}
}
在該程式碼中,我們注意了對指標的釋放卻忽略了對檔案指標的關閉。C++中的動態記憶體需要使用者自己來維護,動態開闢的空間,在出函式作用域或者程式正常退出前必須釋放掉,否則會造成記憶體洩露,有時我們已經非常謹慎了,然防不勝防。
智慧指標(RAII)的存在一開始就是為了解決資源分配即初始化,其解決方案是定義一個類來封裝資源的分配和釋放,在建構函式完成資源的分配和初始化,在解構函式完成資源的清理,可以保證資源的正確初始化和釋放。
所以有了第一代Auto_Ptr
template<class T>
class AutoPtr
{
public:
AutoPtr(T* ptr = NULL)
:_ptr(ptr)
{}
AutoPtr(AutoPtr<T>& s)
:_ptr(s._ptr)
{
s._ptr = NULL;
//經過賦值拷貝,原本的智慧指標s中_ptr 已經指向空
}
AutoPtr<T>& operator=(AutoPtr<T>& s)
{
if (this != &s)
{
if (_ptr)
{
delete _ptr;
}
_ptr = s._ptr;
s._ptr = NULL;
//經過賦值運算子後同樣被置空
}
return *this;
}
T* operator->()const
{
return _ptr;
}
T& operator*()const
{
return *_ptr;
}
~AutoPtr()
{
if (_ptr)
{
delete _ptr;
}
}
private:
T* _ptr;
};
void Funtest1(AutoPtr<char> p)
{}
void Funtest2(AutoPtr<char>& p)
{}
int main()
{
AutoPtr<char> p1(new char);
AutoPtr<char> p2(p1);
//AutoPtr<char> p4(p3); 出錯,不能通過編譯,原因在拷貝建構函式中更改了具有常性的 p3
//Funtest1(p2); 同理,以傳值形式作為函式形參,也要經過拷貝建構函式形成臨時變數p,同理賦值崩潰
Funtest2(p2); //以引用的方式傳遞沒有問題
*p2 = '1';
return 0;
}
由此可見一代Auto_Ptr的缺點都有以下幾點:
1:在Auto_Ptr中經過資源轉移後,p1不能再訪問空間
2:以值傳遞的形式作為函式引數後,一旦呼叫函式,該智慧指標在原函式中也不能訪問空間
3:const物件不能構造同類型物件
針對第一代Auto_Ptr的問題,於是乎有了第二代Auto_Ptr的產生實際上我們是使用一個bool 型別的 資料成員來表明該智慧指標是否具有被析構的能力
template<class T>
class AutoPtr
{
public:
AutoPtr(T* ptr = NULL)
:_ptr(ptr)
, type(false)
{
if (_ptr)
type = true;
}
AutoPtr(const AutoPtr<T>& s)
:_ptr(s._ptr)
, type(s.type)
{
s.type = false;
}
//拷貝建構函式中,將s物件具有析構的能力 type賦給新物件,而s.type賦值為false,說明不具有析構能力
AutoPtr<T>& operator=(const AutoPtr<T>& s)
{
if (this != &s)
{
if (_ptr && type)
{
delete _ptr;
}
_ptr = s._ptr;
type = s.type;
s.type = false;
}
return *this;
}
T& operator*()const
{
return *_ptr;
}
//解構函式中,我們將 type 為true的智慧指標進行析構,從而避開了對同一空間釋放多次的問題
~AutoPtr()
{
if (_ptr && type)
{
delete _ptr;
_ptr = NULL;
type = false;
}
}
private:
T* _ptr;
mutable bool type;
//在成員函式體內只改變了type的值,針對於const物件,我們加關鍵字mutable可以更改type的值
};
void Funtest1(AutoPtr<char> p)
{}
int main()
{
AutoPtr<char> p1(new char);
void Funtest1(p1);
AutoPtr<char> p2(p1);
AutoPtr<char> p3(new char);
AutoPtr<char> p4(p3);
Funtest1(p1);
p1 = p3;
*p3 ='1';
return 0;
}
經過驗證,我們確定基於第一代的修改我們成功的引入了第二代,但是我們引入了一個野指標的問題,一旦對於野指標進行操作,很容易造成問題,
當我們用智慧指標管理一個無名的智慧指標物件時,編譯器會自動優化,呼叫系統的建構函式,如果我們想呼叫我們自己寫的建構函式,我們推匯出智慧指標的第三個版本
template<class T>
class autoptrref
{
public:
autoptrref(T* ptr = NULL)
:_ptr(ptr)
{}
T* _ptr;
};
template<class T>
class autoptr
{
public:
//建構函式
autoptr(T* ptr = NULL)
:_ptr(ptr)
{}
//拷貝建構函式
autoptr(autoptr<T>& ap)
:_ptr(ap._ptr)
{
ap._ptr = NULL;//拷貝完後將ap._ptr置NULL
}
//賦值運算子的過載
autoptr<int>& operator=(autoptr<T>& ap)
{
if (this != &ap)
{
if (_ptr != NULL)
{
delete _ptr;
}
_ptr = ap._ptr;
ap._ptr = NULL;//賦值完後將ap._ptr置NULL
}
return *this;
}
//解決辦法
//過載autoptrref()
operator autoptrref<T>()//將autoptr<T>轉化為autoptrref<T>
{
autoptrref<T> temp(_ptr);
_ptr = NULL;
return temp;
}
//再過載一個拷貝建構函式
autoptr(const autoptrref<T>& apr)
:_ptr(apr._ptr)
{}
~autoptr()//解構函式
{
if (_ptr != NULL)
{
delete _ptr;
}
}
//*的過載
T& operator*()const
{
return *_ptr;
}
//得到原生態指標
T* Get()const
{
return _ptr;
}
private:
T* _ptr;
};
void funtest()
{
autoptr<int> ap(autoptrref<int>(autoptr<int>(new int)));
//用無名的智慧指標拷貝構造智慧指標ap,則不會呼叫我們編寫好得拷貝建構函式,而是呼叫系統自動合成個的拷貝建構函式
} //原因是編譯器的自動優化,解決辦法:重新增加一個類autoptrref,將無名物件的型別轉化為autoptrref
int main()
{
funtest();
return 0;
}
相關推薦
C++智慧指標之auto_ptr
標頭檔案<memory> 總結為一句話:auto_ptr是獨佔指標,它的出現是能夠自動析構動態分配的記憶體,避免記憶體洩漏,但是auto_ptr有很多弊端,下面會通過示例和講解一一將弊端和用法展現出來。 auto_ptr不能初始化為指向非動態記憶體(原因
智慧指標之 Auto_Ptr
在介紹智慧指標之前我們先看以下程式碼: void FunTest() { int *p = new int[10]; FILE* pFile = fopen( "1.txt", "w" ); if (pFile == NULL)
c++ 之四大智慧指標 std::auto_ptr std::shared_ptr std::unuque std::weak_ptr 比較總結
1. 動態記憶體必要性 程式不知道自己需要多少物件; 程式不知道物件的準確型別; 程式需要在多個物件之間共享資料; 2. 動態記憶體在哪裡 程式有靜態記憶體、棧記憶體。靜態記憶體用來儲存區域性static物件、類static資料成員以及定義在任何函式之外的變數
c++自動釋放的指標之——auto_ptr和shared_ptr
假設我們使用一個用來塑模投資行為(例如股票、債券等)的程式庫,其中各式各樣的投資型別整合自一個root class Investment: class Investment { ... };//"投資型別"整合體系中的root class 進一步假設,這個程式庫通過一個工廠模式供應我們
C++智慧指標之unique_ptr
從C++智慧指標之auto_ptr一文中得知:在使用auto_ptr時,可能會不經意的將多個auto_ptr指向同一塊記憶體,造成auto_ptr銷燬釋放時多次釋放同一塊記憶體。為了解決該問題,本文引出了unique_ptr。 顧名思義,unique是唯一的意思。說明它跟auto_p
智慧指標之 shared_ptr 的使用
一、智慧指標 1. 什麼是智慧指標 簡單地說,C++智慧指標是包含過載運算子的類,其行為像常規指標,但智慧指標能夠及時、妥善地銷燬動態分配的資料,並實現了明確的物件生命週期,因此更有價值。 2. 常規指標存在的問題 C++在記憶體分配、釋放和管理方面向程式猿提供了全面的靈
智慧指標(auto_ptr的實現)
舊版的auto_ptr 既然要控制資源的轉移,我們可以多定義一個成員物件_owner來標識該成員物件的資源管理權,在呼叫建構函式建立物件時賦予其資源管理權,即_owner置為true,在呼叫拷貝建構函式、賦值運算子的時候將其管理權釋放,即_owner置為false,就起到了資源管理權的轉
React Native 4 for Android原始碼分析 一《JNI智慧指標之介紹篇》
導讀 React Native 釋出以來將近一年多了,也被抄的火爆到不行,包括RN的中文網和各種資料也很多,加之SE5,Se6語法升級,學習成本並不在RN環境搭建和入門,關鍵還是對JS的掌握入門,不管你是用Native開發,h5開發,還是React
C++11智慧指標之使用shared_ptr實現多型
指標除了管理記憶體之外,在C++中還有一個重要的功能就是實現多型。 程式碼很簡單,還是使用虛擬函式。與原生指標並沒有什麼區別: #include <iostream> #include &
C++:智慧指標之shared_ptr
1.智慧指標 C++中用new來動態分配記憶體,delete手動釋放記憶體來達到動態管理記憶體的目的。因為保證在正確的時間釋放記憶體是非常困難的,忘記釋放記憶體就會產生記憶體洩露。 為了更安全、便捷的使用動態記憶體,C++11標準庫提供了新的智慧指標類來管理
android智慧指標之輕量級指標
C++與JAVA的區別是記憶體需要手動管理,具體的來說就是由NEW分配的記憶體或對像需要手動呼叫delete來手動刪除。這樣就導致一個問題,如果大型軟體中一個對像可能在多個執行緒中有使用,必須出現重複多次引用的情況。那麼我們應該在那個執行緒去釋放了,這樣就可能導致釋放了但還有的執行緒在使用導致記憶體洩露,還有
android智慧指標之強指標和弱指標
LightRefBase是輕量級的,那麼RefBase就應該是重量級的了,它的名字中少了light。Android為神馬要引入這個類呢?想一下這樣一個場景,現在有兩個物件:A和B,物件A中有B的引用,因此B的引用等於1;物件B中有A的引用,因此物件A的引用對於1;現在問題來了,這兩個物件和外界的任何物件都沒有
C++11 智慧指標之 std::shared_ptr 初級學習
shared_ptr概念 shared_ptr基於“引用計數”模型實現,多個shared_ptr可指向同一個動態物件,並維護了一個共享的引用計數器,記錄了引用同一物件的shared_ptr例項的數量。當最後一個指向動態物件的shared_ptr銷燬時,會自動
【C++】智慧指標之引用計數的實現
在C++11的標準中,引入了智慧指標的概念。 相比於auto_ptr而言,其主要缺陷在於在進行指標拷貝的時候,會出現管理權轉移的問題,導致原指標最終編成一個懸掛指標(dangling pointer
C++之智慧指標std::shared_ptr簡單使用和理解
1 智慧指標std::shared_ptr相關知識和如何使用 我們這裡先說下智慧指標std::shared_ptr,因為我看到我我們專案c++程式碼裡面用得很多,我不是不會,所以記錄學習下 先讓ubuntu終端支援c++11,如果自己的電腦還沒配置號,可以先看下我的這篇部落格
C++小知識——記憶體管理之智慧指標
在C++中,動態記憶體的管理是通過一對運算子來完成的: 1)new:在動態記憶體中為物件分配空間並返回一個指向該物件的指標 2)delete:接受一個動態物件的指標,銷燬該物件,並釋放與之關聯的記憶體 因為這樣的原因,我們時常很難確保在正確的時間去釋放記憶體,甚至我們忘記了去釋放記憶體,這
C++之智慧指標和普通指標單例模式兩種實現
1 問題 實現c++的單例模式,這裡測試分別寫了通過智慧指標返回物件和普通返回指標 2 程式碼測試 include <iostream> #include <mutex> #include <m
c++ 之智慧指標:儘量使用std::make_unique和std::make_shared而不直接使用new
關於make_unique的構造及使用例程,MSDN的講解非常詳細 (https://msdn.microsoft.com/zh-cn/library/dn439780.aspx ) 使用過程中,主要有這麼幾個關鍵點: 1. make_unique 同 uni
C++Boost庫學習之智慧指標 shared_ptr
目錄 1.共享指標shared_ptr ^ 使用例子 ^ #include<boost/shared_ptr.hpp> using namespace boost; using std::cout; using std::endl; str
C++智慧指標auto_ptr使用講解
auto_ptr是C++98標準庫提供的一個智慧指標,但已被C++11明確宣告不再支援。 auto_ptr具有以下缺陷: auto_ptr有拷貝語義,拷貝後源物件變得無效,這可能引發很嚴重的問題;而unique_ptr則無拷貝語義,但提供了移動語義,這樣的錯誤