前言
本來這篇文章標題我想起成《關於 vector 的兩個小坑》,後來想想,其實也不算是坑,還是自己對原理性的東西理解的沒做那麼透徹。工作中遇到的很多問題,後來歸根到底都是基礎不牢靠。
vector 擴容
這個問題很經典了,但還是不小心踩到。有乙個需求是要對目標元素進行複製,而目標元素集合是儲存在 vector 裡面,於是簡單思考下就有如下**(大致含義):
void duplidate(vector* element_list, element* element)
void process()
}}看起來好像沒什麼問題,就是當前的 package 物件是否滿足複製的要求,需要的話,就對 package 的成員 owww.cppcns.comrigin_element 進行複製。跑 ut 也正常,然後在測試的時候就 coredump 了。看 mbgjtcore 檔案就是掛在了複製的時候。這裡我一開始就沒明白,乙個簡單的複製為什麼會有 coredump。
檢查了很久 element 複製的場景,甚至想要專門寫乙個拷貝建構函式。最後才恍然大悟, origin_element 指標指向的就是 element_list 裡面的元素, element_list 是整體流程的資料來源, packge 物件是封裝的中間處理物件。之前的開發人員為了方便,直接在 package 物件上儲存了原始的 element 指標,而這個指標指向的是乙個 vector 裡的元素。而我新加的邏輯會往原始的 vector 裡面再新增元素,那麼就有可能導致 vector 擴容,而 vector 擴容會導致整體的複製,從而導致原來指向這些元素的指標都失效了,靠後的 package 物件再去訪問 origin_element 就產生了 coredump。
當然,從設計上來說,就不應該儲存指向 vector 元素的指標,但是這裡有太多舊**牽涉,這裡就不做討論。
vector::erase()
起因是我在**裡面新增了如下**(大致):
void eraseelement(const vector::iterator& element_iter,
vector& element_list)
}然後 cr 的同學提出了乙個疑問是 element_iter 是 const 不可變的,但是在函式裡有擦除了對應的元素,這裡會不會有問題?雖然 ut 都已經跑過了,但是這種寫法的確比較奇怪,於是就藉機學習了一下 vector::erase() 的實現原理跟用法。
erase(iterator) 的實現原理其實不會改變 iterator ,而是把後面的元素乙個個往前移動,相當於是 iterator 指向的元素本身發生了變化,所以可以用 const 來修飾這個 iterator 。但是這裡用 cosnt & 其實是沒有錯但是無用的修飾,除了容易讓人誤判之外,其實沒有什麼實際用途。我之前是為了修正 cpplint 才把reference 改成 const reference。
另外 erase 本身的確比較危險,主要還是 erase 的時候 iterator 本身沒發生變化,但是指向的元素變了,,在很多時候 iterator 會自然地指向下乙個元素,但是mbgjt由於這是未定義的行為,這裡面可能會有不可預期的地方,所以最終改成顯示的獲取返回重新賦值( erase() 會返回下乙個迭代器,但這一點常常被忽略),這樣就能保證安全性了。更安全更推薦的做法應該是使用 remove_if() 這裡就不展開講了。
void eraseelement(vector& element_list,
vector::iterator程式設計客棧 element_iter ) }總結
本文標題: 關於c++中vector的兩個小tips分享
本文位址:
C 兩個小技巧
從新新那裡學來的,記錄一下,感覺還挺不錯,哈哈 一。靈活的在注釋與 間轉換 注釋風格 code here 風格 code here 看一下兩者之間,相差什麼呢?只差乙個斜槓 也就是說,只要刪乙個斜槓,就可以把中間這段 注釋掉,增加乙個斜槓,就可以使中間這段 有效。在寫一些測試 時會比較有用。二。寫個...
C 兩個小技巧
從新新那裡學來的,記錄一下,感覺還挺不錯,哈哈 一。靈活的在注釋與 間轉換 注釋風格 code here 風格 code here 看一下兩者之間,相差什麼呢?只差乙個斜槓 也就是說,只要刪乙個斜槓,就可以把中間這段 注釋掉,增加乙個斜槓,就可以使中間這段 有效。在寫一些測試 時會比較有用。二。寫個...
關於sqlmap的兩個小坑
i春秋作家 lsa 0x00 概述 近日在利用sqlmap注入測試時遇到乙個奇怪的現象,高版本sqlmap無法檢測出注入,但是低版本的可以測出注入,並且能跑出資料不是誤報,經過對比測試和檢視sqlmap原始碼,發現兩個小坑。0x01 情景重現 注入點形式 json whereparams 可注入引數...