参考爱编程的大丙的教程和跟着老师的B站视频学习所做的笔记总结:
c++11实用特性[c/c++项目开发必备技能][完整课程请关注公众号:爱编程的大丙]_哔哩哔哩_bilibili
基于范围的for循环 | 爱编程的大丙 (subingwen.cn)
1.C++11基于范围的for循环,语法格式:
for (declaration : expression) {
// 循环体
}
declaration 表面遍历声明,在遍历过程中,当前被遍历到的元素会被存储到声明的变量中
expression 是要遍历的对象,它可以是 表达式、容器、数组、初始化列表 等
🍒① 基于范围的for信用循环遍历容器,示例代码如下:
// 将容器中遍历的当前元素拷贝到了声明的变量value中,因此无法对容器中的元素进行写操作
void traversal1() {
vector<int> t{1,2,3,4,5,6};
for(auto value : t) {
cout<<value<<" ";
}
cout<<endl;
}
1 2 3 4 5 6
将容器中遍历的当前元素拷贝到了声明的变量value中,因此无法对容器中的元素进行写操作
🍒② 若需要在遍历过程中修改元素的值,需要使用引用
// 若需要在遍历过程中修改元素的值,需要使用引用
void traversal2() {
vector<int> t{1,2,3,4,5,6};
cout<<"遍历修改之前的容器: ";
for(auto &value : t) {
cout<<value++<<" ";
}
cout << endl << "遍历修改之后的容器: ";
for(auto &value : t) {
cout<<value<<" ";
}
cout<<endl;
}
遍历修改之前的容器: 1 2 3 4 5 6
遍历修改之后的容器: 2 3 4 5 6 7
🍒③ 对容器的遍历过程中,如果只是读数据,不允许修改元素的值
// 对容器的遍历过程中,如果只是读数据,不允许修改元素的值,可以使用 const 定义保存元素数据的变
// 量,在定义的时候建议使用 const auto &,这样相对于const auto 效率要更高一些
void traversal3() {
vector<int> t{1,2,3,4,5,6};
for(const auto& value : t) {
cout<<value<<" ";
}
cout<<endl;
}
1 2 3 4 5 6
🍄【方法】:可以使用const 定义保存元素数据的变量,在定义的时候建议使用 const auto &,因为相对于 const auto 效率要更高一些。
2.使用细节
2.1 关系型容器
// 对关系型容器map的遍历:
/*
1.使用普通的for循环方式(基于迭代器)遍历关联型容器,auto自动推导,需要使用迭代器的方式取出元素中的键值对(和指针的操作方法相同)
it->first
it->second
2.使用基于范围的for循环遍历关联性容器,auto自动推导出的类型是容器中的value_type,相当于一个对组(std:pair)对象,提取键值对的方式
如下:
it.first
it.second
*/
void traversal4() {
map<int,string> m{
{1,"heheda"},{2,"Sakura"},{3,"Luffy"}
};
// 1.普通的for循环方式
for(auto it=m.begin();it!=m.end();++it) {
cout<<"id: "<<it->first<<",name: "<<it->second<<endl;
}
// 2.基于范围的for循环方式
for(auto& it : m) {
cout<<"id: "<<it.first<<",name: "<<it.second<<endl;
}
}
id: 1,name: heheda
id: 2,name: Sakura
id: 3,name: Luffy
*******************
id: 1,name: heheda
id: 2,name: Sakura
id: 3,name: Luffy
🍄【总结】
🍒① 基于迭代器遍历关联型容器,auto自动推导,需要使用迭代器的方式取出元素中的键值对(和指针的操作方法相同)
- it->first
- it->second
🍒② 基于范围的for循环遍历关联性容器,auto自动推导出的类型是容器中的value_type,相当于一个对组(std:pair)对象,提取键值对的方式如下:
- it.first
- it.second
2.2 元素只读
情况一:基于范围的for循环语法,内部声明一个变量的引用就可以修改遍历的表达式中的元素的值。但并不适用所有情况,对set容器来说,内部元素都是只读的,由容器的特性来决定的。因此在for循环中auto& 会被视为 const auto&
// 1.不能给具有const限定类型“const int &”的变量“item”赋值
void traversal5() {
set<int> st{1,2,3,4,5,6};
for(auto &item:st) {
cout<<item++<<endl; //error:Cannot assign to variable 'item' with const-qualified type 'const int &'
}
}
error:Cannot assign to variable 'item' with const-qualified type 'const int &'
不能给具有const限定类型“const int &”的变量“item”赋值-----(不能给常量赋值)
情况二:基于范围的for循环中,在遍历关联型容器时也会出现同样的问题,可以得到一个std::pair引用,但是我们是不能修改里边的first值的,也就是key值。
// 2.item.first 是一个常量
void traversal6() {
map<int,string> m{
{1,"lucy"},{2,"lily"},{3,"tom"}
};
for(auto& item : m) {
//error:Cannot assign to non-static data member 'first' with const-qualified type 'const int'
cout << "id: " << item.first++ << ", name: " << item.second << endl;
}
}
error:Cannot assign to non-static data member 'first' with const-qualified type 'const int'
错误:不能给具有const限定类型的非静态数据成员'first'赋值
对一个表达式或者容器/数组等对象,进行基于范围的for循环遍历,请问for循环对这个容器的访问频率是一次还是多次?
// 2.3 访问次数
// 对一个表达式或者容器/数组等对象,进行基于范围的for循环遍历,请问for循环对这个容器的访问频率是一次还是多次?
vector<int> v{1,2,3,4,5,6};
vector<int>& getRange() {
cout<<"get vector range..."<<endl;
return v;
}
void traversal7() {
for(auto val : getRange()) {
cout<<val<<" ";
}
cout<<endl;
}
void traversal8() {
for(auto it = getRange().begin();it!=getRange().end();++it) {
cout<<*it<<" ";
}
cout<<endl;
}
get vector range...
1 2 3 4 5 6
==========================
get vector range...
get vector range...
1 get vector range...
2 get vector range...
3 get vector range...
4 get vector range...
5 get vector range...
6 get vector range...
🍄【实验结果表明】
🍒① 函数getRange()只在第一次迭代之前被调用,得到这个容器对象之后就不会再去重新获取这个对象了,会先确定好迭代的范围,基于这个范围直接进行遍历文章来源:https://www.toymoban.com/news/detail-666467.html
🍒② 相较于普通的for循环,在每次迭代的时候都需要判断是否已到了结束边界文章来源地址https://www.toymoban.com/news/detail-666467.html
到了这里,关于C++11 新特性 ---- 基于范围的for循环的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!