2015-11-30 31 views
1

在這個代碼摘錄請看:遍歷一棵樹,同時取出並重新插入的元素

while(*it <= *it_end and it != myset.end()) 
    if(foo(*it++)) 
     return true; 

itit_end是的std ::設置(的RB樹)的有效迭代器。

foo要麼:

  • 刪除it,並與*it相同的值再次插入一個元素,returing假;
  • 刪除it並返回true。

我的問題:

它是安全運行這個循環?

在調用foo之前,it將成爲樹的下一個元素的有效迭代器,但是恐怕std :: set中的某些內部魔法使該迭代器無效,就像RB的自平衡算法樹。

回答

0

看來,因爲你正在使用的std ::設置

http://www.cplusplus.com/reference/set/set/erase

迭代器的有效性是安全的:

迭代器,指針和引用的函數刪除的元素的引用無效。所有其他迭代器,指針和引用保持其有效性。

增量將在調用foo()之前發生,即在元素被移除之前。換句話說,增量是在迭代器有效時完成的,因此它是安全的。注意 - foo()仍然是用增量前迭代器的值調用的。

該增量發生之前來源於此的事實:

答曰[C++標準] [1] 16年9月1日(從下面的鏈接截取):

調用函數時(是否 不是函數被內聯)中,用任何參數 表達,或與所述後綴 表達指定被叫 功能相關聯的每個 值計算和副作用 ,是 之前測序執行每個表達式或 函數的主體中的語句。 (注:數值計算 並與 不同的觀點表達相關的副作用是 未測序。)

更可以在這裏找到:Is it legal to use the increment operator in a C++ function call?

+1

很有趣的是你的答案是如何嚴格錯誤的,因爲你的ARE混淆了後期和前期增量之間的差異。在調用'foo'之前''它會增加。然而,你粘貼的摘錄確實回答了這個問題,即「是的,它是安全的」。我認爲我應該接受你的答案,並且也會讓它失望,呵呵。 – Kira

+0

@Kira - 是的,我的第一個答案是錯的。不是由於前/後增量的混淆,而是由於在執行foo之前或之後是否執行了增量的混淆。答案已更新。 – 4386427