C++之vector容器的swap方法解讀
C++ vector容器的swap方法
剛才在研究cocos2d-x源碼時(shí),遇到這么幾行代碼:
void AutoreleasePool::clear() { std::vector<Ref*> releasings; releasings.swap(_managedObjectArray); for (const auto &obj : releasings) { obj->release(); } }
AutoreleasePool是一個(gè)用來托管內(nèi)存的對(duì)象池,_managedObjectArray是一個(gè)std::vector<Ref*>類型的成員,用來保存所有管理的對(duì)象,這幾行代碼要做的事情就是:遍歷所有對(duì)象,依次調(diào)用他們的release()方法,最后清空這個(gè)vector。
但是注意到這兩句:
std::vector<Ref*> releasings; releasings.swap(_managedObjectArray);
把一個(gè)默認(rèn)的臨時(shí)對(duì)象和原有的成員進(jìn)行了swap,然后對(duì)交換后的臨時(shí)對(duì)象進(jìn)行遍歷。
這看起來好像是有點(diǎn)多余?
為什么不直接遍歷_managedObjectArray,然后再調(diào)用其clear()方法呢?
《Effective STL》第17條:從vector中刪除元素縮減了該vector的大小(size),但是并沒有減小它的容量(capacity)。
了解STL的同學(xué)都知道size和capacity的區(qū)別,那么這里的swap調(diào)用就能清楚作者意圖了:遍歷完vector后還要釋放其所占的內(nèi)存,簡(jiǎn)單地調(diào)用clear方法并不能解決問題。
swap方法的原理是交換兩個(gè)vector的內(nèi)部指針以達(dá)到“交換整個(gè)容器”的效果,所以在和默認(rèn)的臨時(shí)變量swap后,成員變量_managedObjectArray確實(shí)是個(gè)空的容器(包括內(nèi)存),
臨時(shí)變量在函數(shù)結(jié)束時(shí)析構(gòu),而vector正是在其析構(gòu)函數(shù)中釋放內(nèi)存的,所以在函數(shù)結(jié)束時(shí),所有多余的內(nèi)存都被釋放,一切安好!
同學(xué)們記住了,這樣的技巧可以用來清空一個(gè)vector的內(nèi)存:
vector<T>().swap(_vectorToBeReleased);
其效果等價(jià)于(注意花括號(hào)):
{ vector<T> temp; temp.swap(_vectorToBeReleased); }
該技巧同樣適用于std::string。
C++ vector容器 巧用swap函數(shù)收縮內(nèi)存
學(xué)vector容器互換時(shí)發(fā)現(xiàn)swap函數(shù)還能用來收縮內(nèi)存,記錄一下
首先先隨意創(chuàng)建一個(gè)比較大的容器:
vector<int>v; for(int i=0;i<100000;i++){ v.push_back(i); } //輸出看看容量及大小 cout<<"v的容量為:"<<v.capacity()<<endl; cout<<"v的大小為:"<<v.size()<<endl;
結(jié)果如下:
接著重新設(shè)置一下容器的大小
v.resize(3); cout<<"v的容量為:"<<v.capacity()<<endl; cout<<"v的大小為:"<<v.size()<<endl;
結(jié)果如下:
可以看到此時(shí)容器容量是遠(yuǎn)大于大小的,造成了內(nèi)存浪費(fèi)
用swap函數(shù)收縮內(nèi)存:
vector<int>(v).swap(v); cout<<"v的容量為:"<<v.capacity()<<endl; cout<<"v的大小為:"<<v.size()<<endl;
運(yùn)行結(jié)果:
完美收縮內(nèi)存
接下來解釋一下代碼:
首先vector<int>(v)是利用了v初始化了一個(gè)匿名對(duì)象,這個(gè)匿名對(duì)象會(huì)按照容器v中實(shí)際元素個(gè)數(shù)去初始化,及容量以及大小均為3
而后匿名對(duì)象再調(diào)用swap函數(shù)實(shí)現(xiàn)與容器v的互換,原本的容器v就會(huì)指向這個(gè)容量大小均為3的內(nèi)存塊
匿名對(duì)象現(xiàn)在就指向了容量較大的內(nèi)存塊,由于匿名對(duì)象的特性,該行結(jié)束后,系統(tǒng)會(huì)自動(dòng)回收匿名對(duì)象占用的內(nèi)存,從而實(shí)現(xiàn)了內(nèi)存收縮
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
C語(yǔ)言MFC導(dǎo)出dll回調(diào)函數(shù)方法詳解
這篇文章主要為大家介紹了C語(yǔ)言MFC導(dǎo)出dll回調(diào)函數(shù)方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11C語(yǔ)言全方位講解指針與地址和數(shù)組函數(shù)堆空間的關(guān)系
指針是C語(yǔ)言中一個(gè)非常重要的概念,也是C語(yǔ)言的特色之一。使用指針可以對(duì)復(fù)雜數(shù)據(jù)進(jìn)行處理,能對(duì)計(jì)算機(jī)的內(nèi)存分配進(jìn)行控制,在函數(shù)調(diào)用中使用指針還可以返回多個(gè)值2022-04-04純c實(shí)現(xiàn)異常捕獲try-catch組件教程示例
這篇文章主要為大家介紹了純c實(shí)現(xiàn)異常捕獲try-catch組件教程示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08Qt各種字符轉(zhuǎn)換的實(shí)現(xiàn)示例
本文主要介紹了Qt各種字符轉(zhuǎn)換的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-05-05C++實(shí)現(xiàn)LeetCode(6.字型轉(zhuǎn)換字符串)
這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(6.字型轉(zhuǎn)換字符串),本篇文章通過簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-07-07基于Matlab實(shí)現(xiàn)有雪花飄落的圣誕樹的繪制
圣誕節(jié)快到了(雖然還有十天),一起來用MATLAB畫個(gè)簡(jiǎn)單圣誕樹叭~代碼幾乎取消了全部的循環(huán),因此至少需要17b之后的版本,僅存的循環(huán)用來讓樹旋轉(zhuǎn)起來,讓雪花飄落起來,讓樹頂上的星光搖曳起來~感興趣的可以試一試2022-12-12c++將數(shù)組名作為函數(shù)參數(shù)對(duì)數(shù)組元素進(jìn)行相應(yīng)的運(yùn)算
這篇文章主要介紹了c++將數(shù)組名作為函數(shù)參數(shù)對(duì)數(shù)組元素進(jìn)行相應(yīng)的運(yùn)算,需要的朋友可以參考下2014-05-05??C++11系列學(xué)習(xí)之Lambda表達(dá)式
這篇文章主要介紹了??C++11系列學(xué)習(xí)之Lambda表達(dá)式,C++11終于也引入了lambda表達(dá)式,lambda最早來源于函數(shù)式編程,現(xiàn)代語(yǔ)言慢慢都引入了這個(gè)語(yǔ)法,下文關(guān)于??C++11Lambda表達(dá)式相關(guān)內(nèi)容需要的小伙伴可以參考一下2022-04-04