2013-10-23 108 views
10

to this quite highly upvoted answer Accordint,規範的方式通過一組擦除一些元件進行迭代如下:爲什麼不是mySet.erase(it ++)未定義的行爲,還是它?

for (it = mySet.begin(); it != mySet.end();) { 
    if (conditionToDelete(*it)) { 
     mySet.erase(it++); 
    } 
    else { 
     ++it; 
    } 
} 

此,當然,是C++ 03的組擦除不返回一個迭代的結果。否則,一個人可以寫it = mySet.erase(it);這同樣明顯的是一個可以寫入

itToDelete = it++; 
mySet.erase(itToDelete); 

這個問題不是關於如何刪除,而迭代元素。問題是爲什麼下面的行顯然而不是導致未定義的行爲。

mySet.erase(it++); 

起初我確定這必須是UB,因爲我以錯誤的方式考慮後增量。在前評估的剩餘評估之前發生前增量是一種常見的(但是錯誤的)方法,並且後增量發生在AFTER之後。當然,這是錯誤的。增量和預增量都會增加變量的副作用。不同的是這些表達式的價值。據我所知,C++標準(至少是C++ 03的標準)並沒有明確地指出postincrement的副作用何時發生。因此,除非我們保證如果函數參數是一個後增加表達式,其之前進入函數體,它不應該是UB嗎?究竟什麼(標準方面),如果有的話,禁止它的++的副作用發生在迭代器在函數體內失效之後?

來自標準的報價將非常受歡迎。

對於爭論的緣故,讓我們也假設集合的迭代器是一個內置的類型,這實際上是運營商+ +,而不是重載運算符功能

+1

在控制流進入被調用函數的主體之前,標準是否要求評估所有函數參數? – 2013-10-23 15:45:53

+0

@ H2CO3:評估某物是否涉及其所有副作用? –

+0

我很確定它確實如此,但我正在檢查標準。 – 2013-10-23 15:47:11

回答

11

這不是Çundefined behavior ++ 03,因爲在評估所有函數參數之後,有一個序列點

最接近C++ 03,這是公開可用的是N1804標準草案,也從之前的標準草案沒有公版,我可以找到,但Wikipedia article on sequence points使用C++ 98C++ 03作爲參考,並且該短語與以下段落一致:N1804

在第1.9程序執行款說(重點煤礦前進):

調用函數時(該功能是否是內聯),有一個序列在評估所有函數參數(如果有)之前,在執行函數體中的任何表達式或語句之前發生。 [...]

,後來在第5.2.2函數調用款說:

的參數評價的順序是不確定的。 在輸入函數之前,參數表達式評估的所有副作用都會生效。未指定後綴表達式和參數表達式列表的評估順序。

相關問題