c++11中for循环的注意点

  • Post author:
  • Post category:其他




一、c++11中新增的for循环

在传统的c/c++中,for循环的形式基本就是变量的限制迭代,即使在STL中使用迭代器的本质,其实也是如此。而在c++11中则提供了语法糖的range方法。这种方法其实更好的解决了两个问题,一是对所有数据类型的兼容,不再有原生类型直接遍历,复杂类型需要使用迭代器;二是和auto结合,实现了数据的自动获取而不是原来的强制指定数据类型,应用更方便快捷。

这种语法糖,更多的是提供了一种类似数据库的查询而不是修改(关联式容器),这一点一定要注意。也就是说,不可将其用于大多数的STL中的数据结构的删除和修改,除非有明确的文档说明可以(原生类型和有些类型还是可以修改的)。这种循环方式,应用范围很广,基本上原来可以用for循环的地方都可以直接应用,甚至是返回值是可以遍历的相关数据类型的函数均可。

不过,在c/c++中,由于数组和指针可以转换,需要明确一下,指针代表的数组是不可以使用此种循环方式的。使用这种方式直接拿到相关数据结构的结果(可以是引用,也可以是值),这样的优势就在于省略了类型转换带来的风险,降低了开发者的应用难度。



二、注意事项及例程

1、不能用此种方式增加或者删除元素

void TestDel()
{
    std::unordered_map<int, int> umap;
    for (int i = 0; i < 10; i++)
    {
        umap.emplace(std::make_pair(i, i + 2));
    }

    //删除
    for (auto& d : umap)
    {
        std::cout << d.first << "  " << d.second << std::endl;
        umap.erase(d.first);//这会引发异常
    }
}
int main()
{
    TestDel();
}

上面的代码会引发了异常:“ 读取访问权限冲突。d 是 0xFFFFFFFFFFFFFFFF”。

2、对auto推导的类型要保持强一致

对于一些简单的原生数据类型,可能习惯于凭直觉去做,这也没啥问题,但对一些比较复杂的STL中的数据结构,就有些问题了,比如map系列,还有一些同时支持多种类型的,也需要看到底返回提哪种类型,再做具体的数据解析:

#include <iostream>
#include <unordered_map>

void TestRange()
{
    std::unordered_map<int, int> umap;
    for (int i = 0; i < 10; i++)
    {
        umap.emplace(std::make_pair(i,i+2));
    }

    //看一下为什么不直接显示值
    for (auto& d : umap)
    {
        std::cout << d.first << "  " << d.second << std::endl;
    }
}
int main()
{
    TestRange();
}

一定要注意的是,auto返回的是一个std::pair,这样才能正确的解析数据。

3、对关联容器要明白相关约束

也就是上面提到的关联容器相关的for循环是只读的。看一下相关代码:

void TestSet()
{
    std::set<int> sData;
    for (int i = 0; i < 10; i++)
    {
        sData.emplace(i);
    }

    for (auto& d : sData)
    {
        //此处会有编译提示错误
        d = 3;
    }
}
int main()
{
    TestSet();
}

这个Set就是典型的是一个只读的类型情况,其实包括map的Key也是无法修改的。

其实类似于网上说的在遍历函数返回的容器和字符串时,只执行一次,这个不是for循环的特点,这玩意是编译器进行的优化,同学们一定要明确。



三、总结

c/c++的难度就在于此,到处都是一些小细节,一个把握不好,或者是编程的风格不好,就被带进坑里了。或者说,c/c++对初学者是不友好的。好多刚刚入门的c++程序员,面对着Bug无从下手,甚至有些人说原来这么写,跑越来没问题啊。不是没问题,是工程是Demo性质,错误还来不及显示就退出了。到了真正的工程上,很快就暴露出来了。希望新的c++标准能不断的推陈出新,让更多的人愿意学习c++,让c++能够更有活力。

大道至简,大约如是!

在这里插入图片描述



版权声明:本文为fpcc原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。