• 基于for循环高效率遍历容器方法 C++


    1、常用的iterator遍历容器

    1. std::vector<int> vec {1,2,3,4,5,6,7,8,9,10};
    2. for (std::vector<int>::iterator it = vec.begin(); it != vec.end(); ++it)
    3. cout << *it<
    4. //需注意:遍历时,++it的效率是大于it++的

    上述方法,需要明确给出容器的开始和结束条件,以遍历整个容器;

    2、C++11引入的auto遍历容器(不适用于数组)

    此方法,无需给出容器的开始和结束条件,就可遍历整个容器;此方法遍历容器,效率跟高;

    通用格式:

    1. for(auto temp : 容器name)
    2. {
    3. cout<
    4. }
    5. //temp就是容器中一个元素,数据类型与容器中元素一致,即容器中元素是什么,temp就是什么

     注意:在上述对容器的遍历是只读的,也就是说遍历的值是不可修改的,如果需要修改其中元素,需声明为auto &

    原理:

    1. for(auto it = gate.get_output().begin(), ;it != gate.get_output().end();it++)
    2. {
    3. temp = (*it); //这里,其实已经有了两份内存,temp调用了一次
    4. //这个类对应的构造函数调用构造函数会花费时间,而引用避免了调用构造函数;
    5. // 当然 如果遍历的容器本来就是int类型或者指针类型的(即数据类型并非类),那么二者时间差不多;
    6. // 习惯上最好用引用,可以节省空间
    7. 循环体实质内容;
    8. }

    示例:

    1. #include
    2. using namespace std;
    3. #include
    4. int main()
    5. {
    6. vector<int> vec{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
    7. for(auto &temp:vec)
    8. {
    9. temp=temp*10;
    10. }
    11. for(auto temp: vec)
    12. {
    13. cout<" ";
    14. }
    15. cout<
    16. return 0;
    17. }

    程序运行结果:

     3、auto遍历map容器

    在遍历容器的时候,auto自动推导的类型是容器的value_type类型,而不是迭代器,而map中的value_type是std::pair,也就是说val的类型是std::pair类型的,因此需要使用vec.first,vec.second来访问数据;

    1. #include
    2. using namespace std;
    3. #include
    4. int main()
    5. {
    6. mapint> vec{ {"aa",1},{"bb",2},{"cc",3} };
    7. for(auto &temp:vec)
    8. {
    9. temp.second=temp.second*10;
    10. }
    11. for(auto temp: vec)
    12. {
    13. cout<" "<
    14. cout<
    15. }
    16. cout<
    17. return 0;
    18. }

    程序运行结果:

     4、使用注意

    • 容器本身的约束,导致不可修改容器元素:

    比如set的容器内的元素本身有容器的特性就决定了其元素是只读的,哪怕的使用了引用类型来遍历set元素,也是不能修改器元素的,举例如下:

    1. set<int> vec = { 1, 2, 3, 4, 5, 6 };
    2. for (auto &temp : vec)
    3. cout << temp++ << endl;

    上述代码定义了一个set,使用引用类型遍历set中的元素,然后对元素的值进行修改,该段代码编译失败:error C3892: 'n' : you cannot assign to a variable that is const。同样对于map中的first元素也是不能进行修改的

    • 当冒号后不是容器而是一个函数则冒号后面的函数调用,函数仅会被调用一次
    1. #include
    2. #include
    3. using namespace std;
    4. set<int> vec = { 11, 22, 33, 44, 55, 66 };
    5. const set<int> getSet()
    6. {
    7. cout << "--------GetSet----------" << endl;
    8. return vec;
    9. }
    10. int main()
    11. {
    12. for (auto temp : getSet())
    13. cout << temp << endl;
    14. system("pause");
    15. return 0;
    16. }

    程序运行结果:

    •  不要在for循环中遍历容器时修改容器
    1. #include
    2. #include
    3. using namespace std;
    4. vector<int> vec = { 1, 2, 3, 4, 5, 6 };
    5. int main()
    6. {
    7. for (auto temp : vec)
    8. {
    9. cout << temp << endl;
    10. vec.push_back(100);
    11. }
    12. return 0;
    13. }

    上述代码在遍历vector时,在容器内插入一个元素100,运行上述代码程序崩溃;

    原因:在遍历容器的时候,在容器中插入一个元素导致迭代器失效了,因此,基于范围的for循环和普通的for循环一样,在遍历的过程中如果修改容器,都将造成迭代器失效;

    总结:在基于for循环遍历容器的过程中,可以通过引用&修改容器中的元素,但是不可对容器进行修改;

  • 相关阅读:
    Playwright 配置文件/运行命令/测试标记
    Java之打印流,压缩流,工具包的详细解析
    nginx实现负载均衡load balance
    若依框架解读(前后端分离版)—— 1.Spring Security相关配置(@Anonymous注解)
    3. 堪比JMeter的.Net压测工具 - Crank 进阶篇 - 认识bombardier
    mac 版hadoop3.2.4 解决 Unable to load native-hadoop library 缺失文件
    分类预测 | Matlab实现PSO-LSTM-Attention粒子群算法优化长短期记忆神经网络融合注意力机制多特征分类预测
    生成器创建方式、浅拷贝与深拷贝区别与案例比较
    Redis的开发利用
    初阶JavaEE(17)Linux 基本使用和 web 程序部署
  • 原文地址:https://blog.csdn.net/weixin_42322256/article/details/126567169