c++中的動態記憶體管理通過 new delete運算子來完成的:
new:在動態記憶體中為物件分配空間並且返回乙個指向該物件的指標,可對物件進行初始化;
delete:接受乙個動態物件的指標,銷毀該物件,並釋放與之關聯的記憶體。
首先說一下為什麼使用智慧型指標,存在以下幾種情形:
申請的空間在使用完 甚至程式結束時忘記釋放,這會造成了記憶體洩露;
有時在尚有指標引用記憶體的情況下 記憶體就被釋放了,這會產生非法記憶體的指標(野指標);
現有的智慧型指標有:auto_ptr、shared_ptr、weak_ptr、unique_ptr,其中第乙個auto_ptr已被c++11棄用,後三個是c++11新支援的。
使用智慧型指標很大程度上可以避免上面的問題,因為智慧型指標就是乙個類,當超過了類的作用域,類會自動呼叫析構函式,析構函式會自動釋放資源。使用智慧型指標需要新增標頭檔案memory。
c++98方案,c++11已經棄用,但是這裡還是要講一下:
auto_ptr採用所有權模式:
auto_ptr< string> p1 (new string ("i reigned lonely as a cloud.」));
auto_ptrp2;
p2 = p1; //auto_ptr不會報錯.
此時不會報錯,p2剝奪了p1的所有權,但是當程式執行時訪問p1將會報錯。
所以auto_ptr的缺點是:存在潛在的記憶體崩潰問題!
unique_ptr 替換了auto_ptr,同樣採用了所有權模式。
unique_ptr實現獨佔式擁有或嚴格擁有概念,保證同一時間內只有乙個智慧型指標可以指向該物件。它對於避免資源洩露(例如「以new建立物件後因為發生異常而忘記呼叫delete」)特別有用。
unique_ptrp3 (new string ("auto"));
unique_ptrp4;
p4 = p3;//此時會報錯!!
編譯器認為p4=p3非法,避免了p3不再指向有效資料的問題。因此,unique_ptr比auto_ptr更安全。
另外unique_ptr還有更聰明的地方:當程式試圖將乙個 unique_ptr 賦值給另乙個時,如果源 unique_ptr 是個臨時右值,編譯器允許這麼做;如果源 unique_ptr 將存在一段時間,編譯器將禁止這麼做,比如:
unique_ptrpu1(new string ("hello world"));
unique_ptrpu2;
pu2 = pu1; // #1 not allowed
unique_ptrpu3;
pu3 = unique_ptr(new string ("you")); // #2 allowed
其中#1留下懸掛的unique_ptr(pu1),這可能導致危害。而#2不會留下懸掛的unique_ptr,因為它呼叫 unique_ptr 的建構函式,該建構函式建立的臨時物件在其所有權讓給 pu3 後就會被銷毀。這種隨情況而已的行為表明,unique_ptr 優於允許兩種賦值的auto_ptr 。
注:如果確實想執行類似與#1的操作,要安全的重用這種指標,可給它賦新值。c++有乙個標準庫函式std::move(),讓你能夠將乙個unique_ptr賦給另乙個。例如:
unique_ptrps1, ps2;
ps1 = demo("hello");
ps2 = move(ps1);
ps1 = demo("alexia");
cout << *ps2 << *ps1 << endl;
初始化:必須採用直接初始化形式,不支援普通的拷貝或者賦值操作:
unique_ptrp1; //指向乙個double的unique_ptr
unique_ptrp2 (new int(42) ); //p2指向乙個值為42的的int
unique_ptrp3 (p2); //錯誤:不支援拷貝
p1=p2; //錯誤 不支援賦值
unique操作
雖然不支援拷貝和賦值,但是可以呼叫release或者reset將指標的所有權從乙個(非const)unique_ptr轉移給另乙個unique:
shared_ptr實現共享式擁有概念。多個智慧型指標可以指向相同物件,該物件和其相關資源會在「最後乙個引用被銷毀」時候釋放。從名字share就可以看出了資源可以被多個指標共享,它使用計數機制來表明資源被幾個指標共享。可以通過成員函式use_count()來檢視資源的所有者個數。除了可以通過new來構造,還可以通過傳入auto_ptr, unique_ptr,weak_ptr來構造。當我們呼叫release()時,當前指標會釋放資源所有權,計數減一。當計數等於0時,資源會被釋放。
shared_ptr 是為了解決 auto_ptr 在物件所有權上的侷限性(auto_ptr 是獨佔的), 在使用引用計數的機制上提供了可以共享所有權的智慧型指標。
c++11提供的這兩種智慧型指標( shared_ptr、unique_ptr)的區別在於管理底層指標的方式:
#include #include #include using namespace std;
int main()
};class b
};void fun()
{shared_ptrpb(new b());
shared_ptrpa(new a());
pb->pa_ = pa;
pa->pb_ = pb;
cout可以看到fun函式中pa ,pb之間互相引用,兩個資源的引用計數為2,當要跳出函式時,智慧型指標pa,pb析構時兩個資源引用計數會減一,但是兩者引用計數還是為1,導致跳出函式時資源沒有被釋放(a b的析構函式沒有被呼叫),如果把其中乙個改為weak_ptr就可以了,我們把類a裡面的shared_ptr pb_; 改為weak_ptr pb_; 執行結果如下,這樣的話,資源b的引用開始就只有1,當pb析構時,b的計數變為0,b得到釋放,b釋放的同時也會使a的計數減一,同時pa析構時使a的計數減一,那麼a的計數為0,a得到釋放。
注意的是我們不能通過weak_ptr直接訪問物件的方法,比如b物件中有乙個方法print(),我們不能這樣訪問,pa->pb_->print(); 英文pb_是乙個weak_ptr,應該先把它轉化為shared_ptr,如:shared_ptr p = pa->pb_.lock(); p->print();
智慧型指標總結
1.智慧型指標的原理 1 智慧型指標不是通常意義下的指標,而是乙個模板類,在對模板類例項化之後會產生類似於指標的行為。通過物件來管理資源。2 智慧型指標採用一種raii 資源分配即初始化 機制,在建構函式中實現對資源的分配及初始化,在析構函式中實現對資源的析構及 2.智慧型指標的分類 c 中最開始是...
智慧型指標總結
std shared ptr include class test public std enable shared from this void print intid int main std enable shared from this是乙個模板類,其中有乙個成員函式 shared ptrs...
智慧型指標總結
unique ptr weak ptr 智慧型指標與常規指標的區別 智慧型指標的選擇 智慧型指標並非c 11的原創,boost庫很早就提供了share ptr和weak ptr,c 11在此基礎上增加了unique ptr,從而形成了我們現在所說的智慧型指標。智慧型指標主要用於管理動態記憶體,當智慧...