這篇文章主要介紹C++中vector兩個(gè)小tips的示例分析,文中介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們一定要看完!
創(chuàng)新互聯(lián)基于分布式IDC數(shù)據(jù)中心構(gòu)建的平臺(tái)為眾多戶提供資陽主機(jī)托管 四川大帶寬租用 成都機(jī)柜租用 成都服務(wù)器租用。vector 擴(kuò)容
這個(gè)問題很經(jīng)典了,但還是不小心踩到。有一個(gè)需求是要對(duì)目標(biāo)元素進(jìn)行復(fù)制,而目標(biāo)元素集合是保存在 vector 里面,于是簡單思考下就有如下代碼(大致含義):
void Duplidate(vector* element_list, Element* element) { element_list.push_back(*element); } void Process() { for (auto& package : package_list) { if (IsNeedDuplicate()) { Duplicate(element_list, package->element); } } }
看起來好像沒什么問題,就是當(dāng)前的 package 對(duì)象是否滿足復(fù)制的要求,需要的話,就對(duì) package 的成員 origin_element 進(jìn)行復(fù)制。跑 UT 也正常,然后在測(cè)試的時(shí)候就 coredump 了???core 文件就是掛在了復(fù)制的時(shí)候。這里我一開始就沒明白,一個(gè)簡單的復(fù)制為什么會(huì)有 coredump。
檢查了很久 element 復(fù)制的場(chǎng)景,甚至想要專門寫一個(gè)拷貝構(gòu)造函數(shù)。最后才恍然大悟, origin_element 指針指向的就是 element_list 里面的元素, element_list 是整體流程的數(shù)據(jù)源, packge 對(duì)象是封裝的中間處理對(duì)象。之前的開發(fā)人員為了方便,直接在 package 對(duì)象上保存了原始的 element 指針,而這個(gè)指針指向的是一個(gè) vector 里的元素。而我新加的邏輯會(huì)往原始的 vector 里面再添加元素,那么就有可能導(dǎo)致 vector 擴(kuò)容,而 vector 擴(kuò)容會(huì)導(dǎo)致整體的復(fù)制,從而導(dǎo)致原來指向這些元素的指針都失效了,靠后的 package 對(duì)象再去訪問 origin_element 就產(chǎn)生了 coredump。
當(dāng)然,從設(shè)計(jì)上來說,就不應(yīng)該保存指向 vector 元素的指針,但是這里有太多舊代碼牽涉,這里就不做討論。
vector::erase()
起因是我在代碼里面新增了如下代碼(大致):
void EraseElement(const vector::iterator& element_iter, vector & element_list) { while (element_iter != element_list.end()) { element_list.erase(element_iter); } }
然后 cr 的同學(xué)提出了一個(gè)疑問是 element_iter 是 const 不可變的,但是在函數(shù)里有擦除了對(duì)應(yīng)的元素,這里會(huì)不會(huì)有問題?雖然 UT 都已經(jīng)跑過了,但是這種寫法的確比較奇怪,于是就借機(jī)學(xué)習(xí)了一下 vector::erase() 的實(shí)現(xiàn)原理跟用法。
erase(iterator) 的實(shí)現(xiàn)原理其實(shí)不會(huì)改變 iterator ,而是把后面的元素一個(gè)個(gè)往前移動(dòng),相當(dāng)于是 iterator 指向的元素本身發(fā)生了變化,所以可以用 const 來修飾這個(gè) iterator 。但是這里用 cosnt & 其實(shí)是沒有錯(cuò)但是無用的修飾,除了容易讓人誤判之外,其實(shí)沒有什么實(shí)際用途。我之前是為了修正 cpplint 才把reference 改成 const reference。
另外 erase 本身的確比較危險(xiǎn),主要還是 erase 的時(shí)候 iterator 本身沒發(fā)生變化,但是指向的元素變了,,在很多時(shí)候 iterator 會(huì)自然地指向下一個(gè)元素,但是由于這是未定義的行為,這里面可能會(huì)有不可預(yù)期的地方,所以最終改成顯示的獲取返回重新賦值( erase() 會(huì)返回下一個(gè)迭代器,但這一點(diǎn)常常被忽略),這樣就能保證安全性了。更安全更推薦的做法應(yīng)該是使用 remove_if() 這里就不展開講了。
void EraseElement(vector& element_list, vector ::iterator element_iter ) { while (element_iter != element_list.end()) { element_iter = element_list.erase(element_iter); } }
以上是“C++中vector兩個(gè)小tips的示例分析”這篇文章的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對(duì)大家有幫助,更多相關(guān)知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)網(wǎng)站建設(shè)公司行業(yè)資訊頻道!
另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)建站www.cdcxhl.com,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場(chǎng)景需求。