C++知識點小結(趁熱搬磚三年半的小碼農) 2020年07月2日整理

c++最好用易用的新特性:

c++有哪些坑?

內存泄漏的解決方案:

  1. 智能指針 
  2. 內存池

學習優秀的c++源碼

  1. Nginx
  2. Leveldb
  3. Envoy
  4. Folly
  5. Boost
vector<int> month;
    int cnt=1;
    month.push_back(3);
    for(int i=3;i<=monthCount;i++)
   {
        for(auto &e:month)
        {
            e++;
        }
        for(auto e:month)
        {
            if(e>=3)
            {
                cnt++;
                month.push_back(1);
            }
        }
    }


這段代碼外層for中嵌套了兩個range-for,但是第一個可以用,第二個是不行的,你看出原因了麼?
第二個錯誤在於:range-for中向遍歷的vector中添加了元素。

先給出結論:不能在range-for的循環體中改變遍歷的容器的大小,即不允許遍歷的同時添加或刪除元素!
至於原因,其實也不難理解:

我們都知道,凡是使用了迭代器的循環體中都不能向迭代器所屬的容器添加元素!(C++primer,5e,P99)

因爲對於某些容器,向容器中添加或刪除元素會導致迭代器失效,因此後續遍歷操作都是未定義的。而STL各種容器失效的時機是不同的,感興趣的可以參考這位大神的博客:http://blog.csdn.net/yangquanhui1991/article/details/52077562,所以纔有C++primer中的上述金玉良言。
再回過來看爲何range-for也不可以呢?

這是因爲range-for底層實現時預存了容器的end()值,而一旦遍歷的時候向該容器添加或刪除元素,就會使該預存的end()失效,由上述迭代器失效的問題,就不難明白:range-for的循環體中不允許對該容器添加或刪除元素!

因此上面代碼中的第二個range-for應該改成普通for循環,並且不能使用迭代器遍歷:

    vector<int> month;
    int cnt=1;
    month.push_back(3);
    for(int i=3;i<=monthCount;i++){
        for(auto &e:month){
            e++;
        }
        for(int i=0;i<month.size();i++){//不能使用range-for或迭代器遍歷!
            if(month[i]>=3){
                cnt++;
                month.push_back(1);
            }
        }
    }

其實range-for的這個陷阱在C++ primer第五版裏已經做出了警示,當時看書時也做了記號,只是這種問題真的只有自己犯過一兩次錯誤後才能記得!而且這種錯誤一旦發生,很難發現錯誤根源,編譯期無錯誤無警告,而且運行時不同編譯器執行的結果可能不一樣!因爲迭代器失效後再執行後續循環將是未定義的行爲,所以C++primer建議如果使用迭代器遍歷,每次在插入或刪除元素後都應該重新定位迭代器,對於這點在寫程序時一定要有一個清醒的認識。
 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章