基于 range 的 for 循环和 auto

C++11 引入一种循环的新形式,叫基于 range 的 for 循环,它允许我们用更简单易读的形式遍历容器中的所有元素

vector<int> v{1, 2, 3};
for (int i : v) {
cout << i << endl;
}

可以使用 auto 来让编译器来推导元素的类型,上面的循环可以改写为

for (auto i : v) {
cout << i << endl;
}

根据 auto 的推导规则,推导出的类型是初始值退化后的类型,即

  • 去掉引用
  • 去掉 const、volatile 限定符
  • 函数和数组将变为指针

根据这个规则,上面循环推导出的类型应该是 int,这对于 int 这种标量类型可能没有问题,但如果容器里存的是类类型,就可能带来巨大的拷贝开销,因为每次做循环都需要创建容器元素的局部副本,这种情况下,应该用 auto &

for (auto& elem : container)    // capture by (non-const) reference

这种形式中修改 elem 将影响容器的内容

对于模板代码,总是应该用这种形式,因为你没法确定模板类型的拷贝开销是否廉价

如果是只读的,还应该给 auto 加上 const 限定符

for (const auto& elem : container)    // capture by const reference

代理迭代器

如果容器使用“代理迭代器”(比如 std::vector<bool> ),应该使用

for (auto&& elem : container)    // capture by &&

假设我们想要用 range-for 遍历一个 std::vector<bool> 并修改它的元素

vector<bool> v = {true, false, false, true};
for (auto& x : v)
x = !x;

会发现上面这段代码无法通过编译,因为 std::vector 模板对 bool 类型做了模板特化,对 bool 元素做了打包处理以压缩空间(把 8 个布尔值存到一个字节里)

由于你无法返回一个 bit 的引用,std::vector<bool> 用了一种叫“代理迭代器”的模式

代理迭代器是一种迭代器,当它被解引用时,它不产生原始的 bool &,而是返回一个临时对象,它是可以转换为 bool 的代理类

为了对 std::vector<bool> 使用 range-for 语法,必须使用 auto&& 来引用 bool 元素(关于 auto && 的推导规则请看这篇

这种语法对于没有使用代理迭代器的容器也适用,因此在泛型代码里,最好的选择就是用这种形式来遍历修改容器元素

基于 range 的 for 循环和 auto的更多相关文章

  1. C++ 11 学习2:空指针(nullptr) 和 基于范围的for循环(Range-based for loops)

    3.空指针(nullptr) 早在 1972 年,C语言诞生的初期,常数0带有常数及空指针的双重身分. C 使用 preprocessor macroNULL 表示空指针, 让 NULL 及 0 分别 ...

  2. 第9课 基于范围的for循环

    1. 基于范围的for循环(range-based for) (1)语法:for(decl : coll){//statement} ①decl用于声明元素及类型,如int elem或auto ele ...

  3. C++11基于范围的for循环

    C++11包含一种新的 for 循环,称为基于范围的 for 循环,可以简化对数组元素的遍历.格式如下: for(Type VarName : Array){ //每个元素的值会依次赋给 VarNam ...

  4. 基于范围的for循环(STL)

    1. ]={4.99,5.99,6.99,7.99,8.99}; for (double x : prices) cout<<x<<endl; //////////////// ...

  5. 基于范围的for循环(C++11)

    C++11新增了一种循环:基于范围的for循环.这简化了一种常见的循环任务:对数组(或容器类,如vector和array)的每个元素执行相同的操作,如下例所示 for语句允许简单的范围迭代:(只遍历, ...

  6. c++11 基于范围的for循环

    c++11 基于范围的for循环 #define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <string> # ...

  7. c++11——基于范围的for循环

    c++11中有基于范围的for循环,基于范围的for循环可以不再关心迭代器的概念,只需要关系容器中的元素类型即可,同时也不必显式的给出容器的开头和结尾. int arr[] = {1, 2, 3, 4 ...

  8. C++11特性中基于范围的for循环

    本文摘录柳神笔记:   除了像C语⾔的for语句 for (i = 0; i < arr.size(); i++) 这样,C++11标准还为C++添加了⼀种新的 for 循环⽅ 式,叫做基于范围 ...

  9. Atitit.升级软件的稳定性---基于数据库实现持久化 循环队列 循环队列

    Atitit.升级软件的稳定性---基于数据库实现持久化  循环队列 环形队列 1. 前言::选型(马) 1 2. 实现java.util.queue接口 1 3. 当前指针的2个实现方式 1 1.1 ...

随机推荐

  1. Spring根据路径前缀获取不同Resource

    相关文章:https://www.jianshu.com/p/5bab9e03ab92 官方文档:https://docs.spring.io/spring/docs/current/spring-f ...

  2. (stm32学习总结)—LCD—液晶显示

    显示器简介 显示器属于计算机的 I/O 设备,即输入输出设备.它是一种将特定电子信息输出到屏幕上再反射到人眼的显示工具.常见的有 CRT 显示器.液晶显示器.LED 点阵显示器及OLED 显示器 本章 ...

  3. vim recording的使用方法

    使用vim时无意间触碰到q键,左下角出现"recording"这个标识,觉得好奇,遂在网上查了一下,然后这是vim的一个强大功能.他可以录 制一个宏(Macro),在开始记录后,会 ...

  4. PCB产业链、材料、工艺流程详解(1)

    PCB知识大全 1.什么是pcb,用来干什么? PCB( Printed Circuit Board),中文名称为印制电路板,又称印刷线路板,是重要的电子部件,是电子元器件的支撑体,是电子元器件电气连 ...

  5. template7入门教程及对它的一些看法

    template7是framework7的内置模板引擎,在此之前使用过jquery-tmpl,不过刚刚打开github看了下,已经停止更新,并且将要被JsRender所替代.妹的,JsRender又是 ...

  6. github 上有趣又实用的前端项目(持续更新,欢迎补充)

    github 上有趣又实用的前端项目(持续更新,欢迎补充) 1. reveal.js: 幻灯片展示框架 一个专门用来做 HTML 幻灯片的框架,支持 HTML 和 Markdown 语法. githu ...

  7. AMS分析 -- 启动过程

    一. AMS简介 AmS可以说是Android上层系统最核心的模块之一,其主要完成管理应用进程的生命周期以及进程的Activity,Service,Broadcast和Provider等. 从系统运行 ...

  8. 字符串反转&说反话

    题目描述 写出一个程序,接受一个字符串,然后输出该字符串反转后的字符串.(字符串长度不超过1000) 输入描述: 输入N个字符 输出描述: 输出该字符串反转后的字符串 示例1 输入 abcd 输出 d ...

  9. EL表达式详解(常用表达式以及取值)

    EL表达式 学习总结 一. El表达式概念 二. El中的表达式 1. 算术表达式 2. 比较表达式 3. 逻辑表达式 4. 三元表达式 5. 判空表达式 三.EL 从四个作用域中取值 1. 概念 2 ...

  10. Struts的Logic标签的用途

    Struts的Logic标签可以根据特定的逻辑条件来判断网页的内容,或者循环遍历集合元素,它和HTML,Bean标签是Struts应用中最常用的三个标签. 它的功能主要是比较运算,进行字符串的匹配,判 ...