在c++中一般在建構函式中進行資源申請,在析構函式中進行資源釋放,在c語言中有可能在某函式內部進行資源申請,在函式呼叫處進行資源釋放,資源的申請和釋放不在同一處非常容易產生記憶體洩漏問題。
c++記憶體會出現問題:
我們來看乙個問題:
#includeusing namespace std;
void func(int *ptr)//ptr = null
*p = *ptr;
delete p;
}int main()
在丟擲異常前有動態申請,在異常呼叫點丟擲異常後,就會跳轉出去,不會在執行delete語句,則會造成記憶體洩露
這個時候就需要智慧型指標的出現了。
《c++ primer第五版》中這樣描述智慧型指標的:
我們知道除了靜態記憶體和棧記憶體外,每個程式還有乙個記憶體池,這部分記憶體被稱為自由空間或者堆。程式用堆來儲存動態分配的物件即那些在程式執行時分配的物件,當動態物件不再使用時,我們的**必須顯式的銷毀它們。
在c++中,動態記憶體的管理是用一對運算子完成的:new和delete,new:在動態記憶體中為物件分配一塊空間並返回乙個指向該物件的指標,delete:指向乙個動態獨享的指標,銷毀物件,並釋放與之關聯的記憶體。
動態記憶體管理經常會出現兩種問題:一種是忘記釋放記憶體,會造成記憶體洩漏;一種是尚有指標引用記憶體的情況下就釋放了它,就會產生引用非法記憶體的指標。
為了更加容易(更加安全)的使用動態記憶體,引入了智慧型指標的概念。智慧型指標的行為類似常規指標,重要的區別是它負責自動釋放所指向的物件。標準庫提供的兩種智慧型指標的區別在於管理底層指標的方法不同,shared_ptr允許多個指標指向同乙個物件,unique_ptr則「獨佔」所指向的物件。標準庫還定義了一種名為weak_ptr的伴隨類,它是一種弱引用,指向shared_ptr所管理的物件,這三種智慧型指標都定義在memory標頭檔案中。
圖中p1,p2都指向堆上同乙個物件itnterting,p1與p2屬於兩個不同的執行緒,如果執行緒a通過指標p1對物件進行了銷毀且置為空,那麼p2就成為了懸垂指標,如上圖右圖所示
我們來解決下這個問題 正確的方法應該是所有不再被使用的物件都應該偷偷地銷毀
通過加入中間層間接地完成對資源的銷毀,即引入proxy**
proxy物件結構上是乙個類,行為上是指標,通過引用計數完成對當前指向物件的指標計數。此時有兩個指標sp1和sp2指向物件interting。當sp1和sp2依次析構後,引用計數降為0,此時就可以安全地銷毀proxy和interting了。
這也正是引用計數型智慧型指標的本質!
**實現:
templateclass smart_ptr
smart_ptr(const smart_ptr& rhs)
:ptr(rhs.mptr)
smart_ptr& operator = (const smart_ptr& rhs)
return *this;
}~smatr_ptr()
private:
/*在拷貝函式裡面在函式體進入之前已經有兩個智慧型指標指向同一塊物件的記憶體,現在要做的事改變舊指標指向,改變rhs的指向,置為空
*///將當前指標的指向置為空
void release()const
t*mptr;//最後管理堆記憶體
};int main()
類似vector,建立智慧型指標的時候必須提供額外的資訊--指標可以指向的型別格式:
shared_ptr《型別》智慧型指標的名字
例項化:
shared_ptrp1;//shared_ptr,可以指向string
shared_ptr> p2;//shared_ptr,可以指向int的list
智慧型指標的使用方式:與普通指標類似。解引用乙個智慧型指標返回它指向的物件智慧型指標一定要被初始化,若不被初始化它就會變成乙個空指標
用new返回的指標來初始化智慧型指標
指標引數的職能指標是explicit的,因此我們不能將乙個內建指標隱式轉換為乙個智慧型指標,必須直接初始化形式來初始化乙個智慧型指標:
shared_ptrp1 = new int(1024);//錯誤:必須使用直接初始化形式
shared_ptrp2(new int(1024));//正確:使用了直接初始化形式
智慧型指標物件提前釋放,導致其他指標出現錯誤,因為拷貝構造或者賦值的時候,讓兩個指標物件指向了同一塊記憶體,所引發的函式
template class smart_ptr
smart_ptr(const smart_ptr& rhs):mptr(rhs.mptr)
smart_ptr& operator = (const smart_ptr& rhs)
return *this;
}
~smart_ptr()
mptr = null;
}t& operator*()
t*operator->()
private:
t * mptr;
mutable bool flag;//mutable去除常性
}void func(smart_ptrsp)
int main()
c 智慧型指標
auto prt 它是 它所指向物件的擁有者 所以當自身物件被摧毀時候,該物件也將遭受摧毀,要求乙個物件只有乙個擁有者,注意 auto prt 不能使用new 來分配物件給他 include include using namespace std template void bad print au...
c 智慧型指標
很久沒寫部落格了,不知道如何表達了,哈哈.我先介紹一下深淺拷貝.class copy 此時a.ptr和b.ptr指向同乙個物件,當我們delete a.ptr時 b.ptr所指向的物件已經不存在了,要是我們引用b.ptr指向的物件也就會出問題了.深拷貝 把a.ptr所指向的物件拷貝乙份給b.ptr ...
c 智慧型指標
記得前不久有一次面試被問到智慧型指標的實現,當時對智慧型指標只是聽說但沒有了解過,就亂七八糟地說了一遍。今天寫了一遍智慧型指標,用了引用計數的概念。主要思想就是,用乙個新類對原本需要的型別進行了一層封裝,這個新類中儲存了原本的物件指標和乙個引用計數的指標,之所以全部用指標來儲存,就是因為會出現多個新...