C++ vector容器的swap方法

我想造輪子發表於2017-11-01

剛才在研究cocos2d-x原始碼時,遇到這麼幾行程式碼:

void AutoreleasePool::clear()
{
    std::vector<Ref*> releasings;
    releasings.swap(_managedObjectArray);
    for (const auto &obj : releasings)
    {
        obj->release();
    }
}

AutoreleasePool是一個用來託管記憶體的物件池,_managedObjectArray是一個std::vector<Ref*>型別的成員,用來儲存所有管理的物件,這幾行程式碼要做的事情就是:遍歷所有物件,依次呼叫他們的release()方法,最後清空這個vector。

但是注意到這兩句:

std::vector<Ref*> releasings;
releasings.swap(_managedObjectArray);

把一個預設的臨時物件和原有的成員進行了swap,然後對交換後的臨時物件進行遍歷。這看起來好像是有點多餘?為什麼不直接遍歷_managedObjectArray,然後再呼叫其clear()方法呢?

《Effective STL》第17條:從vector中刪除元素縮減了該vector的大小(size),但是並沒有減小它的容量(capacity)。

瞭解STL的同學都知道size和capacity的區別,那麼這裡的swap呼叫就能清楚作者意圖了:遍歷完vector後還要釋放其所佔的記憶體,簡單地呼叫clear方法並不能解決問題。

swap方法的原理是交換兩個vector的內部指標以達到“交換整個容器”的效果,所以在和預設的臨時變數swap後,成員變數_managedObjectArray確實是個空的容器(包括記憶體),

臨時變數在函式結束時析構,而vector正是在其解構函式中釋放記憶體的,所以在函式結束時,所有多餘的記憶體都被釋放,一切安好!

同學們記住了,這樣的技巧可以用來清空一個vector的記憶體:

vector<T>().swap(_vectorToBeReleased);

其效果等價於(注意花括號):

{
    vector<T> temp;
    temp.swap(_vectorToBeReleased);
}

該技巧同樣適用於std::string。


相關文章