国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > C++ > 正文

關(guān)于C++中vector的兩個小tips分享

2020-01-26 13:28:12
字體:
供稿:網(wǎng)友

前言

本來這篇文章標題我想起成《關(guān)于 vector 的兩個小坑》,后來想想,其實也不算是坑,還是自己對原理性的東西理解的沒做那么透徹。工作中遇到的很多問題,后來歸根到底都是基礎(chǔ)不牢靠。

vector 擴容

這個問題很經(jīng)典了,但還是不小心踩到。有一個需求是要對目標元素進行復(fù)制,而目標元素集合是保存在 vector 里面,于是簡單思考下就有如下代碼(大致含義):

void Duplidate(vector<Element>* element_list, Element* element) {element_list.push_back(*element);}void Process() {for (auto& package : package_list) {if (IsNeedDuplicate()) {Duplicate(element_list, package->element);}}}

看起來好像沒什么問題,就是當前的 package 對象是否滿足復(fù)制的要求,需要的話,就對 package 的成員 origin_element 進行復(fù)制。跑 UT 也正常,然后在測試的時候就 coredump 了???core 文件就是掛在了復(fù)制的時候。這里我一開始就沒明白,一個簡單的復(fù)制為什么會有 coredump。

檢查了很久 element 復(fù)制的場景,甚至想要專門寫一個拷貝構(gòu)造函數(shù)。最后才恍然大悟, origin_element 指針指向的就是 element_list 里面的元素, element_list 是整體流程的數(shù)據(jù)源, packge 對象是封裝的中間處理對象。之前的開發(fā)人員為了方便,直接在 package 對象上保存了原始的 element 指針,而這個指針指向的是一個 vector 里的元素。而我新加的邏輯會往原始的 vector 里面再添加元素,那么就有可能導(dǎo)致 vector 擴容,而 vector 擴容會導(dǎo)致整體的復(fù)制,從而導(dǎo)致原來指向這些元素的指針都失效了,靠后的 package 對象再去訪問 origin_element 就產(chǎn)生了 coredump。

當然,從設(shè)計上來說,就不應(yīng)該保存指向 vector 元素的指針,但是這里有太多舊代碼牽涉,這里就不做討論。

vector::erase()

起因是我在代碼里面新增了如下代碼(大致):

void EraseElement(const vector<Element>::iterator& element_iter,vector<Element>& element_list) {while (element_iter != element_list.end()) {element_list.erase(element_iter);}}

然后 cr 的同學(xué)提出了一個疑問是 element_iter 是 const 不可變的,但是在函數(shù)里有擦除了對應(yīng)的元素,這里會不會有問題?雖然 UT 都已經(jīng)跑過了,但是這種寫法的確比較奇怪,于是就借機學(xué)習(xí)了一下 vector::erase() 的實現(xiàn)原理跟用法。

erase(iterator) 的實現(xiàn)原理其實不會改變 iterator ,而是把后面的元素一個個往前移動,相當于是 iterator 指向的元素本身發(fā)生了變化,所以可以用 const 來修飾這個 iterator 。但是這里用 cosnt & 其實是沒有錯但是無用的修飾,除了容易讓人誤判之外,其實沒有什么實際用途。我之前是為了修正 cpplint 才把reference 改成 const reference。

另外 erase 本身的確比較危險,主要還是 erase 的時候 iterator 本身沒發(fā)生變化,但是指向的元素變了,,在很多時候 iterator 會自然地指向下一個元素,但是由于這是未定義的行為,這里面可能會有不可預(yù)期的地方,所以最終改成顯示的獲取返回重新賦值( erase() 會返回下一個迭代器,但這一點常常被忽略),這樣就能保證安全性了。更安全更推薦的做法應(yīng)該是使用 remove_if() 這里就不展開講了。

void EraseElement(vector<Element>& element_list,vector<Element>::iterator element_iter ) {while (element_iter != element_list.end()) {element_iter = element_list.erase(element_iter);}}

總結(jié)

以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,謝謝大家對武林網(wǎng)的支持。

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 临城县| 汉沽区| 贡嘎县| 义马市| 明水县| 崇阳县| 岗巴县| 左云县| 宝应县| 侯马市| 华蓥市| 苗栗县| 尚志市| 安吉县| 安泽县| 丹寨县| 江达县| 霍山县| 临清市| 寿光市| 大石桥市| 二连浩特市| 镇雄县| 全椒县| 香格里拉县| 通道| 娱乐| 乌拉特前旗| 甘洛县| 涞源县| 广饶县| 定安县| 宁乡县| 新田县| 东至县| 晋宁县| 离岛区| 墨江| 长岭县| 长泰县| 郧西县|