想要搶先看後面的章節?打賞本文10元,即可獲得帶插圖全本下載地址!打賞完成記得私信我哦 :p

12.2.3 智能指針shared_ptr的應用場景

既然智能指針shared_ptr能夠幫助我們對程序中的內存資源進行很好的管理,避免內存泄漏或者內存訪問錯誤的發生,那麼我們能不能在任何時候都使用它來管理程序中的內存資源呢?

不能。就像東坡肘子再好吃,我們也不可能天天吃。同樣的道理,就算shared_ptr的作用再好再強大,我們也不可能處處使用。在這個世界上,任何的得到都是以某種犧牲為代價的。shared_ptr為了得到能夠在內存資源的使用者個數為0時自動釋放這塊內存資源的能力,它增加了額外的引用計數而犧牲了一定的性能。如果在不需要shared_ptr的場景下過度濫用shared_ptr,不僅無助於內存資源的管理,反而可能會影響程序的性能,最終得不償失。只有在合適的場景下使用shared_ptr,才能起到事半功倍的效果。

總結起來,當出現以下情況時應該優先考慮使用shared_ptr來管理內存資源:

? 有多個使用者共同使用同一個對象,而這個對象沒有一個明確的擁有者;

這就好比教室里的電燈,大家都在使用這個電燈,但沒有那個人來專門負責這個電燈的開關。往往是教室里一個人都沒有,電燈卻明晃晃地亮著。在這種場景下,我們就可以使用shared_ptr來管理這個電燈,通過shared_ptr,誰都可以使用這個電燈,但誰最後使用電燈誰就負責最後關燈。

? 某一個對象的複製操作很費時;

如果一個對象的複製操作很費時,同時我們又需要在函數間傳遞這個對象,我們往往會選擇傳遞指向這個對象的指針來代替傳遞對象本身,以此來避免對象的複製操作。既然選擇使用指針,那麼使用shared_ptr是一個更好的選擇,即起到了向函數傳遞對象的作用,又不用為釋放對象操心。

? 要把指針存入標準庫容器;

不管容器中保存的是普通指針還是智能指針,在使用上,兩者並無太大區別,使用智能指針的優越性主要體現在容器使用完畢後清空容器的操作上。如果容器中保存的是普通指針,當我們在清空某個容器時,先要釋放容器中指針所指向的資源,然後才能清空這些指針本身。例如,在SalarySys類的析構函數中,我們需要清空vecEmp容器中保存的Employee*指針:

class SalarySys
{
// …
public:
~SalarySys()
{
// …
// 首先,釋放容器中普通指針所指向的資源
for(Employee* p : m_vecEmp)
{
delete p; // 釋放指針所指向的對象
}
// 然後,用clear()函數清空容器
m_vecEmp.clear();
}
// …
private:
vector<Employee*> vecEmp; // 保存普通指針的容器
}

如果把這個vecEmp容器中的普通指針替換成相應的shared_ptr,這個過程會簡單的多。我們只需要使用clear()函數清空容器中保存的shared_ptr,而隨著shared_ptr的釋放,它會自動釋放它所管理的資源,而無需我們主動去釋放:

class SalarySys
{
// …
public:
~SalarySys()
{
// …
// 用clear()函數釋放容器中的shared_ptr
// shared_ptr在釋放的時候也會連帶地釋放它所管理的Employee對象
m_vecEmp.clear();
}
// …
private:
vector<shared_ptr<Employee>> vecEmp; // 保存shared_ptr的容器
}

? 當管理需要特殊清除方式的資源時,可以通過定製shared_ptr的刪除器來實現。

這一場景可以參考後文對定製shared_ptr刪除器的介紹。

推薦閱讀:

相关文章