网站首页 > 基础教程 正文
C++ 11 中新增了range方式的for语句,对于遍历数组、容器等对象时提供了更便利的语法描述,C++ 20对range形式的for语句进行了改进,在讨论具体改进前,先回顾一下 C++ 11 定义的range形式的for语句。
range形式的for语句基础
C++ 11 定义的range形式的for语句的具体语法如下:
for ( range_declaration : range_expression ) loop_statement
其中的 range_expression 是一个表达式,执行结果是一个序列,可以是一个数组,或者是一个类的对象实例,这个对象有 begin() 和 end() 方法(可以是类成员变量,或者是独立的函数)。而 range_declaration 是定义一个变量,类型是序列的单个成员。
然后在for循环的每一次遍历中,range_declaration 都指向序列的下一个值,然后在循环体 loop_statement 中,可以使用这个值进行运算。
例如下面的代码:
vector<int> v1 = { 1, 2, 3, 4 };
for( const auto & v : v1 ) {
cout << v << endl;
}
相当于:
vector<int> v1 = { 1, 2, 3, 4 };
for( auto pv = v1.begin(); pv != v1.end(); ++pv ) {
auto v = *pv;
cout << v << endl;
}
使用range形式,能够自动选择遍历数组,还是调用成员函数begin()和end(),还是调用独立的函数begin()和end(),这样对于模板推导时,更加简便。
C++20对range形式for语句的改进(1):增加初始化语句
首先,C++20对range形式的for语句,增加了初始化语句,支持在初始化语句中定义变量,这个变量的生命周期只在for语句内,但是对每次for循环都保持有效,同时也不会影响到for语句外面。
class SA
{
public:
std::vector< int > & Items() { return m_data; }
private:
std::vector< int > m_data { 1, 2, 3, 4 };
};
SA func() { return SA{}; }
// <1> 错误代码,func()产生的临时对象会提前被释放,未定义行为
for( auto x : func().Items() ) {
cout << x << endl;
}
// <2> 在for外面定义变量,在for整个循环过程都有效,保证for循环的正确性
// 但for循环之后还有效,可能生命周期过长超出期望,除非再加一个大括号来限定
SA a1 = func();
for( auto x : a1.Items() ) {
cout << x << endl;
}
// <3> C++ 20 新增语法,支持在range形式的for语句中增加初始化语句
// a2定义的变量不会提前释放,保证了for循环的正确性,同时生命周期也限定在for循环之内
for( SA a2 = func(); auto x : a2.Items() ) { // <3>
cout << x << endl;
}
C++20对range形式for语句的改进(2):优化对begin()/end()的查找
C++17中,对于一个类,如果本身只有一个名为begin()或者end()的成员函数,不是成对,此时是无法用在range形式的for语句中的,即使额外定义独立的begin()和end()函数也无济于事。
C++20中,对这种情况进行了改进,要求类成员函数同时有begin()和end()函数时,才会使用类成员函数,否则还是会去继续去找独立的begin()和end()函数,这样就不会被类本身的单个函数所影响。
class SA
{
public:
// <1> 不成对的 end() 函数,C++17会使用这个,但缺少begin()函数因此出错
// 但 C++ 20改进之后,会跳过这个不成对的end()函数,继续进行查找
std::vector< int >::iterator end() { return m_data2.end(); }
private:
friend std::vector< int >::iterator begin( SA & a );
friend std::vector< int >::iterator end( SA & a );
std::vector< int > m_data { 5, 6, 7, 8 };
std::vector< int > m_data2 { 1, 2, 3, 4 };
};
// <2> C++ 20中会查找到这两个成对的 begin() 和 end() 函数,支持用来对SA类实例进行遍历
std::vector< int >::iterator begin( SA & a ) { return a.m_data.begin(); }
std::vector< int >::iterator end( SA & a ) { return a.m_data.end(); }
for( SA a; auto x : a ) {
cout << x << endl;
}
【往期回顾】
猜你喜欢
- 2024-10-19 C语言中的`for`关键字是一种循环控制结构
- 2024-10-19 写给所有人的编程思维-循环篇(for循环)
- 2024-10-19 在PLC编程中,循环语句FOR和WHILE怎么选?
- 2024-10-19 C语言for循环基本流程 c语言for循环程序
- 2024-10-19 C++20尝鲜:基于范围for c++ 范围for
- 2024-10-19 BAT批处理命令之for bat文件中for用法
- 2024-10-19 C语言for循环解析 c语言中for循环
- 2024-10-19 Java Web实战篇:增强for循环实现原理及for循环实战性能优化
- 2024-10-19 1分钟教你学会for循环 for循环教程
- 2024-10-19 C++阶乘:一个数的阶乘和一个范围的阶乘之和
- 最近发表
- 标签列表
-
- gitpush (61)
- pythonif (68)
- location.href (57)
- tail-f (57)
- pythonifelse (59)
- deletesql (62)
- c++模板 (62)
- css3动画 (57)
- c#event (59)
- linuxgzip (68)
- 字符串连接 (73)
- nginx配置文件详解 (61)
- html标签 (69)
- c++初始化列表 (64)
- exec命令 (59)
- canvasfilltext (58)
- mysqlinnodbmyisam区别 (63)
- arraylistadd (66)
- node教程 (59)
- console.table (62)
- c++time_t (58)
- phpcookie (58)
- mysqldatesub函数 (63)
- window10java环境变量设置 (66)
- c++虚函数和纯虚函数的区别 (66)