c++最好用易用的新特性:
- auto/decltype https://blog.csdn.net/zyc2018/article/details/93591189
- nullptr
- range-for
- using
c++有哪些坑?
內存泄漏的解決方案:
- 智能指針
- 內存池
學習優秀的c++源碼
- Nginx
- Leveldb
- Envoy
- Folly
- 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建議如果使用迭代器遍歷,每次在插入或刪除元素後都應該重新定位迭代器,對於這點在寫程序時一定要有一個清醒的認識。