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建议如果使用迭代器遍历,每次在插入或删除元素后都应该重新定位迭代器,对于这点在写程序时一定要有一个清醒的认识。
 

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