智能指針
原生指針是一款很強大的工具,但是依據進數十年的經驗,可以確定的一點是:稍有不慎,這 個工具就會反噬它的使用者。
C++11標準中規定了四個智能指針:
std::auto_ptr,std::unique_ptr,std::shared_ptr,std::weak_ptr.他們都是用來輔助管理動態分配對象的聲明週期。
std::unique_ptr
當要使用一個智能指針的時候,首先要想到的應該是std::unique_ptr。默認情況下,std::unique_ptr和原生指針同等大小,對於大多數操作,他們執行的底層指令也一樣。
std::unique_ptr具現了獨佔語義,一個非空的std::unique_ptr永遠擁有它指向的對象。
很容易將一個std::unique_ptr轉化爲std::shared_ptr.
std::unique_ptr<Widget> getWidget();
std::shared_ptr<Widget> pWidget = getWidget();
std::shared_ptr
std::shared_ptr通過引用計數來管理對象的生命週期。std::shared_ptr的構造函數自動遞增這個計數,析構函數自動遞減這個計數。如果std::shared_ptr在執行減一後發現引用計數變成了0,說明沒有其他的std::shared_ptr在指向這個資源了,所以std::shared_ptr直接析構了它指向的空間。
std::shared_ptr是std::unique_ptr的兩倍大,除了控制塊,還有需要原子引用計數操作引起的開銷
避免從原生指針類型變量創建std::shared_ptr,若無法避免,請使用new
auto pw = new Widget;
std::shared_ptr<Widget> spw1(pw);
std::shared_ptr<Widget> spw2(pw); // 到此爲止,爲pw創建了兩個智能指針,且其計數都分別爲1,當進行釋放時,第一次析構沒有問題,第二次析構時pw已經不存在了,這就產生了一個未定義行爲
std::shared_ptr spw1(new Widget); // 直接使用new
std::shared_ptr spw2(spw1); // 這樣就沒有問題了
std::weak_ptr
std::weak_ptr不能被單獨使用,它是std::shared_ptr作爲參數的產物。std::weak_ptr通常有一個std::shared_ptr來創建,他們指向相同地址,std::shared_ptr來初始化他們,但是std::weak_ptr不會影響到它所指對象的引用計數。
auto spw = std::make_shared<Widget>();
std::weak_ptr<Widget> wpw(spw);
spw = nullptr;
if (wpw.expired())
{
/* code */
}