当前位置: 首页 > news >正文

C++11范围for循环:高效遍历新方式

目录

一、传统遍历方式的局限性

二、基于范围的for循环语法

基本语法

三、使用示例

1、遍历数组

2、遍历标准容器

3、使用auto自动推导类型

4、修改容器元素

四、使用条件

1、迭代范围必须明确

2、迭代对象需要支持迭代器操作

五、底层实现原理

工作原理

六、注意事项

1、引用与拷贝:

2、临时范围表达式:

3、不支持的情况:

4、性能考虑:

5、重点:

七、自定义类型支持


一、传统遍历方式的局限性

在C++98中,遍历数组通常采用以下方式:

int arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};// 将数组元素值全部乘以2
for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++) {arr[i] *= 2;
}// 打印数组中的所有元素
for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++) {cout << arr[i] << " ";
}
cout << endl;

这种传统方式存在几个问题:

  1. 需要手动计算数组长度

  2. 循环控制变量(i)需要显式声明和管理

  3. 容易产生越界错误

  4. 代码冗长,意图不够直观


二、基于范围的for循环语法

        基于范围的for循环(range-based for loop)是C++11引入的一种简化循环语法,它提供了一种更简洁的方式来遍历容器或数组中的所有元素。

基本语法

for (declaration : range_expression) {// 循环体
}

其中:

  • declaration(声明部分):定义一个变量,每次迭代时它会被初始化为当前元素的值,通常使用auto自动推导类型

  • range_expression(范围部分:表示要遍历的序列(如数组、容器等)

  • for (声明 : 范围) 是基本语法结构

  • 可以使用continue结束本次循环,或break跳出整个循环

int arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};// 将数组元素值全部乘以2
for (auto& e : arr) {e *= 2;
}// 打印数组中的所有元素
for (auto e : arr) {cout << e << " ";
}
cout << endl;

三、使用示例

1、遍历数组

int arr[] = {1, 2, 3, 4, 5};for (int num : arr) {cout << num << " ";
}
// 输出: 1 2 3 4 5

2、遍历标准容器

std::vector<std::string> words = {"Hello", "World", "C++"};for (const auto& word : words) {cout << word << " ";
}
// 输出: Hello World C++

3、使用auto自动推导类型

std::list<double> values = {1.1, 2.2, 3.3};for (auto value : values) {cout << value << " ";
}
// 输出: 1.1 2.2 3.3

4、修改容器元素

std::vector<int> nums = {1, 2, 3};for (auto& num : nums) {num *= 2;  // 修改元素
}// nums现在是 {2, 4, 6}

四、使用条件

1、迭代范围必须明确

  • 对于数组:编译器能确定首元素和末元素的位置

  • 对于类:需要提供begin()end()方法,定义迭代范围

2、迭代对象需要支持迭代器操作

  • 迭代器需要实现++(前进)和==(比较)操作

  • 实际上,任何提供了begin()end()方法并返回迭代器的类型都可以使用范围for


五、底层实现原理

范围for循环的底层实现基于迭代器:

  • 对于数组:转换为传统的指针遍历

  • 对于容器:转换为使用该容器的迭代器进行遍历

  • 可以通过查看汇编代码验证这一实现方式

工作原理

基于范围的for循环在底层会被编译器转换为传统的迭代器循环。例如:

for (auto& item : container) {// ...
}

大致等价于:

{auto&& __range = container;auto __begin = begin(__range);auto __end = end(__range);for (; __begin != __end; ++__begin) {auto& item = *__begin;// ...}
}

六、注意事项

1、引用与拷贝

  • 使用auto item会创建元素的拷贝

  • 使用auto& item会创建元素的引用(可修改原元素)

  • 使用const auto& item会创建常量引用(不可修改原元素)

2、临时范围表达式

for (auto x : getTemporaryVector()) { /* ... */ }  // 临时对象会延长生命周期

3、不支持的情况

  • 不能用于指针数组(除非知道数组大小)

  • 不能用于动态分配的数组

  • 不能用于不提供begin()/end()成员或自由函数的类型

4、性能考虑

  • 对于简单类型,使用autoauto&性能差异不大

  • 对于复杂类型,避免不必要的拷贝

5、重点:

  1. 当需要修改元素时,迭代变量应声明为引用类型(使用&

  2. 对于不需要修改的只读访问,使用非引用形式更高效

  3. 范围for循环不支持直接获取当前元素的索引位置

  4. 在循环过程中不应修改容器的大小(如添加/删除元素)

        基于范围的for循环大大简化了集合遍历的代码,提高了可读性和安全性,是现代C++编程中推荐使用的遍历方式。


七、自定义类型支持

要让自定义类型支持基于范围的for循环,需要提供begin()end()成员函数或自由函数:

class MyContainer {int data[5] = {1, 2, 3, 4, 5};
public:int* begin() { return data; }int* end() { return data + 5; }// 也可以提供const版本
};MyContainer c;
for (int x : c) {cout << x << " ";
}
http://www.dtcms.com/a/326538.html

相关文章:

  • Django ORM查询技巧全解析
  • 【LLM】OpenAI开源GPT级模型,120B及20B参数GPT-OSS
  • 如何在 Ubuntu 24.04 LTS Linux 上安装和使用 Flatpak
  • Oracle自动采集AWR Gets TOP SQL脚本
  • Spring Cloud 过滤器工厂
  • Go选手如何快速上手第三方库
  • 机器视觉的PCB板对位印刷加工应用
  • python—day1
  • U-Boot常用命令完全指南
  • 线程的同步与互斥
  • 基于深度学习的异常检测算法在时间序列数据中的应用
  • QT QProcess + xcopy 实现文件拷贝
  • AcWing 6479. 点格棋
  • 数据结构-排序(2)
  • 嵌入式 - Linux软件编程:标准IO
  • 文件夹生成器,一键批量生成,效率提升!
  • 1.Apollo Planning 模块总结
  • 一键生成AI视频!Spring Cloud微服务架构的AgentAlVideo平台开源啦!
  • 内存问题排查工具ASan初探
  • 【liunx】web高可用---nginx
  • AR 智能眼镜:从入门到未来
  • DDIA第五章:复制
  • PCB批量线路板厂家有哪些?
  • LAMPLNMP 最佳实践
  • Ubuntu 22.04 离线环境下 Python 包与 FFmpeg 安装全攻略​
  • 嵌入式Linnux学习 -- 软件编程2
  • linux下部署 dify,并配置本地ollama大模型
  • 【排序算法】⑤冒泡排序
  • Java学习 -- 可变参数与Collections工具类
  • docker安装Engine stopped