指針的缺陷
using std::string;
void remodel(string &str) {
string *ps = new string (str);
str = *ps;
return ;
}
你可能已經(jīng)發(fā)現(xiàn)了其中的缺陷鸟妙。remodel函數(shù)每次被調(diào)用時都會申請一段內(nèi)存,但是從不收回快压。這樣會導(dǎo)致內(nèi)存泄漏圆仔。解決方法是在return語句前添加釋放內(nèi)存的語句。
delete ps;
但是當(dāng)遇到下面這種情況時蔫劣,你可能會忘了釋放內(nèi)存坪郭。
using std::string;
void remodel(string &str) {
string *ps = new string (str);
if(wrong()) {//we get something wrong
throw exception();
}
str = *ps;
delete ps;
return;
}
如果程序出現(xiàn)異常,throw將直接實現(xiàn)跳轉(zhuǎn)脉幢,delete語句不會被執(zhí)行歪沃,內(nèi)存無法釋放嗦锐。
常用的智能指針類
=============
為了解決這個問題,STL設(shè)計了三種智能指針模版:auto_ptr沪曙、unique_ptr和shared_ptr奕污。可以將new獲得的地址賦給這種對象液走。
要使用智能指針模版碳默,首先需要包含頭文件memory。
#include <memory>
以下是修改過的remodel函數(shù)
using std::string;
using std::auto_ptr;
void remodel(string &str) {
auto_ptr <string> ps (new string (str));
if(wrong())
throw exception();
str = *ps;
return;
}
每個智能指針都將存放在一個代碼塊里缘眶,這樣離開代碼塊時嘱根,指針將過期。
智能指針模版類的定義方式?jīng)Q定了智能指針對象很多方面都類似常規(guī)指針比如可以訪問結(jié)構(gòu)成員巷懈、賦值給指向相同類型的常用指針该抒。
三種智能指針的應(yīng)用范圍
==================
首先我們來看一段代碼
auto_ptr<string> p1(new string("auto"));
auto_ptr<string> p2;
p2 = p1;
在賦值語句中,p2接管了string對象的所有權(quán)后顶燕,p1的所有權(quán)將被剝奪凑保。這是智能指針的一個特性,以防止p1和p2的析構(gòu)函數(shù)銷毀相同的對象涌攻。但是如果程序隨后想要用到p1對象欧引,則會發(fā)生錯誤。
unique_ptr和shared_ptr分別以兩種不同的方式解決了這個問題癣漆。在unique_ptr中维咸,賦值語句將會出現(xiàn)報錯信息剂买。當(dāng)程序試圖將一個unique_ptr賦給另外一個的時候惠爽,如果源unique_ptr是一個臨時右值,很快會被銷毀瞬哼,沒有機會使用它訪問無效的數(shù)據(jù)婚肆,編譯器便不會報錯。當(dāng)如果你要執(zhí)意執(zhí)行賦值時坐慰,而編譯器又會出現(xiàn)報錯時较性,請使用move函數(shù),但是需要處理好對象間的關(guān)系结胀。
unique_ptr <int> p1(new string("unique"));
unique_ptr <int> p2;
p2 = move(p1);
而shared_ptr則以一種更智能的方式來解決這類問題赞咙。shared_ptr會跟蹤引用特定對象的智能指針數(shù)。這成為引用計數(shù)糟港。如賦值時攀操,指針計數(shù)+1,指針過期時秸抚,計數(shù)-1速和。僅當(dāng)最后一個指針過期時歹垫,才調(diào)用delete。
如果程序要使用指向同一個對象的多個指針颠放,應(yīng)選擇shared_ptr排惨。如用一個指針數(shù)組指示數(shù)據(jù)并輔助用一些指針來標(biāo)示特定元素(最大最小值)。
這種情況就需要shared_ptr碰凶。而在其他情況下暮芭,不需要多個指向同一個對象的指針,則建議使用unique_ptr欲低。實際上在C++11中谴麦,auto_ptr已經(jīng)被摒棄。