基于 range 的 for 循环和 auto
基于 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的更多相关文章
- C++ 11 学习2:空指针(nullptr) 和 基于范围的for循环(Range-based for loops)
3.空指针(nullptr) 早在 1972 年,C语言诞生的初期,常数0带有常数及空指针的双重身分. C 使用 preprocessor macroNULL 表示空指针, 让 NULL 及 0 分别 ...
- 第9课 基于范围的for循环
1. 基于范围的for循环(range-based for) (1)语法:for(decl : coll){//statement} ①decl用于声明元素及类型,如int elem或auto ele ...
- C++11基于范围的for循环
C++11包含一种新的 for 循环,称为基于范围的 for 循环,可以简化对数组元素的遍历.格式如下: for(Type VarName : Array){ //每个元素的值会依次赋给 VarNam ...
- 基于范围的for循环(STL)
1. ]={4.99,5.99,6.99,7.99,8.99}; for (double x : prices) cout<<x<<endl; //////////////// ...
- 基于范围的for循环(C++11)
C++11新增了一种循环:基于范围的for循环.这简化了一种常见的循环任务:对数组(或容器类,如vector和array)的每个元素执行相同的操作,如下例所示 for语句允许简单的范围迭代:(只遍历, ...
- c++11 基于范围的for循环
c++11 基于范围的for循环 #define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <string> # ...
- c++11——基于范围的for循环
c++11中有基于范围的for循环,基于范围的for循环可以不再关心迭代器的概念,只需要关系容器中的元素类型即可,同时也不必显式的给出容器的开头和结尾. int arr[] = {1, 2, 3, 4 ...
- C++11特性中基于范围的for循环
本文摘录柳神笔记: 除了像C语⾔的for语句 for (i = 0; i < arr.size(); i++) 这样,C++11标准还为C++添加了⼀种新的 for 循环⽅ 式,叫做基于范围 ...
- Atitit.升级软件的稳定性---基于数据库实现持久化 循环队列 循环队列
Atitit.升级软件的稳定性---基于数据库实现持久化 循环队列 环形队列 1. 前言::选型(马) 1 2. 实现java.util.queue接口 1 3. 当前指针的2个实现方式 1 1.1 ...
随机推荐
- Cookie与HttpSession对象
Cookie与HttpSession对象的作用 维护客户端浏览器与服务端会话状态的两个对象. 由于HTTP协议是一个无状态的协议,因此服务端不会记录当前客户端浏览器的访问状态 有些时候需要服务端能够记 ...
- Linux基础学习 | gcc、g++的安装和使用
安装gcc 1.apt-get命令是debain Linux发新版的APT软件包管理工具. dabian.ubuntu.deepin等Linux系统通过以下命令: 安装gcc:Shell输入sudo ...
- 放大器(PA+LAN)在射频上的应用
转自 动手又动脑才会有创造 放大器,包括两种,PA与LAN,功率放大器(PA) 和低噪声放大器(LNA),在射频上,PA用于信号的输出放大,而LNA用天线端的输入放大,一般的,LAN会比PA的放大倍数 ...
- HTTP1.1、HTTP2、HTTP3 演变
推荐阅读:https://www.cnblogs.com/zwtblog/tag/计算机网络/ 目录 HTTP 基本概念 HTTP/1.1 相⽐ HTTP/1.0 提⾼了什么性能? HTTP/1.1如 ...
- 体验javascript之美6:如果你觉得什么都会了或者不知道js学什么了看这里-面向对象编程
概述 当大家已经把js的语言基础理解了,然后能够写出一些简单的例子了,这个时候基本上达到了一年工作经验的水平,而自己能够独立的写一些小功能,完成一些小效果,或者临摹修改一些比较复杂的插件的时候差不多就 ...
- 用Node处理文件上传
前言 在Web开发中,文件上传是一个非常常见.非常重要的功能.本文将介绍如何用Node处理上传的文件. 需求分析 由于现在前后端分离很流行,那么本文也直接采用前后端分离的做法.前端界面如下: 用户从浏 ...
- java中异常这种技术框架是怎么工作的?
异常这种技术框架是怎么工作的?马克-to-win:注意是运行程序时,而不是编译时,当一个非正常情况出现,比如除0,就叫异常情况.马克-to- win:为了能优雅的处理异常情况(在出现异常情况后,程序不 ...
- formData请求接口传递参数格式
element ui组件方法的传递 //引入 组件. <el-upload class="avatar-uploader" :action="action" ...
- 实现一个promise.all方法
思路: 1:首先明白all的用法 2:promise.all可以接受一个由promise数组作为参数,并且返回一个promise实例, 3:promise.all([a,b,c...]).then方法 ...
- QT 如何让release生成的EXE可在他人电脑上运行(尝试了全网的方法后,这应该能帮你解决)
这两天,迅速上手了QT并用其基于C++编写了一个含UI的小程序 跳过中间的开发阶段 当我兴致满满的要将程序打包时,却是费尽周折,搜尽全网的关于QT的打包教程,最后都不顶用. 后面自己和队友的共同发现, ...