智能指針介紹
當(dāng)我們在使用new動態(tài)分配內(nèi)存時,有時候會忘記將分配的內(nèi)存釋放,例如,一個常規(guī)指針p,當(dāng)p過期時p占據(jù)的內(nèi)存將被釋放,如果此前沒有調(diào)用delete釋放p指向的內(nèi)存,就會導(dǎo)致內(nèi)存泄漏。
如果指針p是一個對象的話,那么就能夠在p被刪除時,調(diào)用它的析構(gòu)函數(shù)去釋放p指向的內(nèi)存,從而簡化了動態(tài)內(nèi)存管理,這就是智能指針的思想。
使用智能指針
在頭文件memory中定義了智能指針模板類:auto_ptr,unique_ptr,shared_ptr。(auto_ptr在C++11中被摒棄)
shared_ptr有一個如下構(gòu)造函數(shù),接受一個指針作為參數(shù):
template <class U>
explicit shared_ptr (U* p)
因此可以將new獲得的地址,賦值給智能指針對象,來創(chuàng)建一個智能指針:
shared<string> p(new string);
此構(gòu)造函數(shù)為explicit所以不支持隱式轉(zhuǎn)換:
shared<string> p;
string* s = new string;
p = s //隱式轉(zhuǎn)換不支持,這是錯誤的
智能指針的操作與常規(guī)指針類似,使用(*p),下面為智能指針使用演示程序:
class Person {
private:
std::string name;
public:
Person(const std::string& s):name(s){}
~Person() { std::cout << "Object delete" << std::endl; }
void view()const { std::cout << "Name: " << name << std::endl; }
};
int main() {
{
std::shared_ptr<Person> ps(new Person("Tom"));
ps->view();
}
{
std::unique_ptr<Person> pu(new Person("Bob"));
pu->view();
}
}

當(dāng)智能指針過期時,調(diào)用了它的析構(gòu)函數(shù),來釋放Person對象。
智能指針使用注意事項
現(xiàn)在考慮兩個智能指針指向同一塊內(nèi)存的情況,當(dāng)兩個指針都過期時,程序?qū)⑨尫磐粔K內(nèi)存兩次。
為解決這個問題shared_ptr采用以下措施:
跟蹤引用特定對象的智能指針數(shù)(引用計數(shù))。僅當(dāng)最后一個指針過期時,才調(diào)用delete。
unique_ptr的解決方案:
建立所有權(quán)概念,對于特定的對象,只有一個智能指針可以擁有它,只有擁有對象的智能指針才可以釋放它。并且,賦值操作將轉(zhuǎn)讓所有權(quán),轉(zhuǎn)讓所有權(quán)后指針不再指向有效數(shù)據(jù)。這個過程將會非常嚴(yán)格。
下面是unique_ptr處理此問題的兩個例子:
unique_ptr<string> p1(new string("unique")); //#1
unique_ptr<string> p2; //#2
p2 = p1; //#3 非法語句
對于上述例子,轉(zhuǎn)讓所有權(quán)后p1將不再指向有效數(shù)據(jù),為了避免p1不再指向有效數(shù)據(jù),對于語句#3編譯器將會認(rèn)為是非法的
假設(shè)又如下函數(shù)定義:
unique_ptr<string> demo(){
std::unique_ptr<string> p(new string("dome"));
return p;
}
unique_ptr<string> p2;
p2 = demo();
這時p2 = demo()將是合法的賦值操作,因為demo返回一個臨時對象,賦值完成后將被銷毀。