看板 C_and_CPP 關於我們 聯絡資訊
※ 引述《renderer (rendering)》之銘言: : ※ 引述《khoguan (Khoguan Phuann)》之銘言: : : 所謂「標準寫法」其實和原po寫的差不多,只是沒有另外設一個 : : 暫時變數來存下一個 iterator 的值,而是用 postfix ++ 來做。 : : if (/* 符合條件 */) : : child.erase(i++); : : else : : ++i; : 對喔 iterator++ 是 iterator 自己先加 然後傳一份原來的給 statement 做處理 : 不過在感情上總覺得 它不是掛了嗎 怎麼還有辦法 ++ Orz 您這種感情是有合理的基礎的。;-Q : 問一個額外的問題 對於 primitive type 如 int : i++ 編輯器的處理是 : 做完 statement 再加 i 還是 : i 自己先加 但是傳一份原本的 i 給 statement 做處理 i++ 一般簡單的說法都是「先」取值「再」加一。這只是比較容易 解釋,也比較容易聽得懂的說法。其實這兩者並無必然的先後關係。 int i = 10; i++; cout << i; i++ 是一個式子(expression, 而 i++; 多了分號的是 statement), 這整個式子會有一個evaluate後的值,這個值當然還是它原來的值(10), 但是,它另外也會有 side effect,也就是對 i 這個東東做加一的 動作。所以執行到 cout << i; 這個statement時,i 已經變成了 11。 但是加一這個動作到底是在那個精確的時間點完成的呢? i++; 敘述中的 i++ 是一個 full expression (因為它不是其他 expression 的 subexpression, 若是 i++ + 1; 這個敘述中的 i++ 就只是 subexpression)。一個 full expression 後面會有一個 概念上的 sequence point,所有在它之前的 side effect 到達 這個點時,都必須全部完成(而這個點之後的 side effect 則 必須尚未開始)。也就是在上一個 sequence point (A) 與下一個 sequence point (B)之間的所有 side effect 都要在到達 B 時 完成,不過,並不要求得要剛好就在 B 點完成,只要在這段期間內 完成即可,而不硬性規定(unspecified)。這是為了給編譯環境依其 軟硬體特性產生最有效率的機器碼,而容許這種彈性。 至於最上面那個 child.erase(i++); 要進入那個函式之前,也會有 一個 sequence point, 所以 i++ 的 side effect 的部份也會完成, i 這個 iterator 已經順利的指向下一個 map element 了。而erase() 函式本身接到的引數是原先的 iterator 值(rvalue),將它所對應的 元素刪掉,對 map/set/list 等 node-based container 來說,不會 讓其他的 iterator(包括已經指向下一個 map element 的 i) 也失效, 所以 i 可以繼續安全的使用。 嚴格說來,child.erase(i++); 裡的 ++ 是 overloaded operator function 不過效果還是和內建的 ++ 類似,都會在進入 erase() 之前就完成。 -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 220.130.208.168
jeunder:真熱心, 快去申請板主啦, 還在這不務正業 :( 61.230.216.76 07/01
※ 編輯: khoguan 來自: 220.130.208.168 (07/01 15:36)
khoguan:嗚~~ jeunder你們這些高人都不來帶領大家220.130.208.168 07/01
sekya:但是我記得erase正確用法是 i = child.erase( i ); 59.104.35.123 07/01
sekya:erase的內部動作,說不定會變整個array都變掉。 59.104.35.123 07/01
sekya:增刪各元素的時候,理論上iterator都要重取才對。 59.104.35.123 07/01
khoguan:map/set 和 vector/deque 不同220.130.208.168 07/01
khoguan:請再看一下 8223 篇220.130.208.168 07/01