2016-01-06 16 views
3

我在亂搞,我遇到了一些行爲,我發現使用修改x_vectorfor(auto x: x_vector)循環時特別。我想看看,如果我修改了我正在循環的向量會導致問題。編譯器如何處理其中x_vector被修改的(auto x:x_vector)?

這裏是整個代碼我編譯和運行沒有任何錯誤:

#include<iostream> 
#include<vector> 
int main(int argc,char* argv[]){ 
    std::vector<int> vec1 = {1,2,3,4,5,6}; 
    std::vector<int> vec2 = {2,3,4,5,6,7}; 
    for(auto n1: vec1){ 
     std::cout << "at vec1" << n << " vec2 is {"; 
     for(auto n2: vec2){ 
      std::cout << " " << n2 << " "; 
      if (n<n2) vec2.push_back(n); 
     } 
     std::cout<< "}" << std::endl; 
    } 
    return 0; 
} 

我預計如果沒有錯誤,我會得到這樣的輸出:

at vec1 1 vec2 is { 2 3 4 5 6 7 1 1 1 1 1 1 } 
at vec1 2 vec2 is { 2 3 4 5 6 7 1 1 1 1 1 1 2 2 2 2 2 } 
at vec1 3 vec2 is { 2 3 4 5 6 7 1 1 1 1 1 1 2 2 2 2 2 3 3 3 3 } 
at vec1 4 vec2 is { 2 3 4 5 6 7 1 1 1 1 1 1 2 2 2 2 2 3 3 3 3 4 4 4 } 
at vec1 5 vec2 is { 2 3 4 5 6 7 1 1 1 1 1 1 2 2 2 2 2 3 3 3 3 4 4 4 5 5 } 
at vec1 6 vec2 is { 2 3 4 5 6 7 1 1 1 1 1 1 2 2 2 2 2 3 3 3 3 4 4 4 5 5 6 } 

凡第一次內循環被執行(n1 = 1),在循環到達矢量的該部分之前,已經存在對於已經存在的每個元素的vec 2的末端附加1,因此通過打印不小於1的6 1完成然後去vec1的下一個元素,所以第四...

相反,我得到這個:

at vec1 1 vec2 is { 2 3 4 5 6 7 } 
at vec1 2 vec2 is { 2 3 4 5 6 7 1 1 1 1 1 1 } 
at vec1 3 vec2 is { 2 3 4 5 6 7 1 1 1 1 1 1 2 2 2 2 2 } 
at vec1 4 vec2 is { 2 3 4 5 6 7 1 1 1 1 1 1 2 2 2 2 2 3 3 3 3 } 
at vec1 5 vec2 is { 2 3 4 5 6 7 1 1 1 1 1 1 2 2 2 2 2 3 3 3 3 4 4 4 } 
at vec1 6 vec2 is { 2 3 4 5 6 7 1 1 1 1 1 1 2 2 2 2 2 3 3 3 3 4 4 4 5 5 } 

凡看來,1的加在第一遍V2的結束不會「出現」,直到第二和6的加在最後一傳不根本不出現。

有人可以解釋這種行爲嗎?我真的不明白髮生了什麼,或者爲什麼如果在內部循環中修改矢量時有某種延遲,甚至會編譯它。

回答

3

這有未定義的行爲。通過vec2.push_back(n);修改矢量將使迭代器無效,並且使用那些失效的迭代器來覆蓋vec2範圍內的循環。

基本上,如果要修改循環內的範圍,請不要使用基於範圍的循環。請改用傳統的for循環,並注意正確更新迭代器。

+0

未確定的行爲究竟意味着什麼?我可以指望下一次循環播放時更新的矢量,即使它在循環播放時沒有更新嗎? – Ajay

+0

@Ajay - UB意味着任何事情都可能發生。 Prtactically,我很驚訝它沒有崩潰 –

+2

通常未定義的行爲導致不正確的邏輯(跳過執行路徑)或崩潰(如果你是幸運的)。如果調用未定義的行爲,C和C++將允許ANY行爲。如果你調用未定義的行爲,即使這是合法的:https://xkcd.com/416/ – Graznarak