参考爱编程的大丙的教程和跟着老师的B站视频学习所做的笔记总结:
c++11实用特性[c/c++项目开发必备技能][完整课程请关注公众号:爱编程的大丙]_哔哩哔哩_bilibili
基于范围的for循环 | 爱编程的大丙 (subingwen.cn)
for (declaration : expression) {
// 循环体
}
declaration 表面遍历声明,在遍历过程中,当前被遍历到的元素会被存储到声明的变量中
expression 是要遍历的对象,它可以是 表达式、容器、数组、初始化列表 等
// 将容器中遍历的当前元素拷贝到了声明的变量value中,因此无法对容器中的元素进行写操作
void traversal1() {
vector t{1,2,3,4,5,6};
for(auto value : t) {
cout<
1 2 3 4 5 6
将容器中遍历的当前元素拷贝到了声明的变量value中,因此无法对容器中的元素进行写操作
// 若需要在遍历过程中修改元素的值,需要使用引用
void traversal2() {
vector t{1,2,3,4,5,6};
cout<<"遍历修改之前的容器: ";
for(auto &value : t) {
cout<
遍历修改之前的容器: 1 2 3 4 5 6
遍历修改之后的容器: 2 3 4 5 6 7
// 对容器的遍历过程中,如果只是读数据,不允许修改元素的值,可以使用 const 定义保存元素数据的变
// 量,在定义的时候建议使用 const auto &,这样相对于const auto 效率要更高一些
void traversal3() {
vector t{1,2,3,4,5,6};
for(const auto& value : t) {
cout<
1 2 3 4 5 6
【方法】:可以使用const 定义保存元素数据的变量,在定义的时候建议使用 const auto &,因为相对于 const auto 效率要更高一些。
// 对关系型容器map的遍历:
/*
1.使用普通的for循环方式(基于迭代器)遍历关联型容器,auto自动推导,需要使用迭代器的方式取出元素中的键值对(和指针的操作方法相同)
it->first
it->second
2.使用基于范围的for循环遍历关联性容器,auto自动推导出的类型是容器中的value_type,相当于一个对组(std:pair)对象,提取键值对的方式
如下:
it.first
it.second
*/
void traversal4() {
map m{
{1,"heheda"},{2,"Sakura"},{3,"Luffy"}
};
// 1.普通的for循环方式
for(auto it=m.begin();it!=m.end();++it) {
cout<<"id: "<first<<",name: "<second<
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自动推导,需要使用迭代器的方式取出元素中的键值对(和指针的操作方法相同)
② 基于范围的for循环遍历关联性容器,auto自动推导出的类型是容器中的value_type,相当于一个对组(std:pair)对象,提取键值对的方式如下:
情况一:基于范围的for循环语法,内部声明一个变量的引用就可以修改遍历的表达式中的元素的值。但并不适用所有情况,对set容器来说,内部元素都是只读的,由容器的特性来决定的。因此在for循环中auto& 会被视为 const auto&
// 1.不能给具有const限定类型“const int &”的变量“item”赋值
void traversal5() {
set st{1,2,3,4,5,6};
for(auto &item:st) {
cout<
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 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 v{1,2,3,4,5,6};
vector& getRange() {
cout<<"get vector range..."<
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()只在第一次迭代之前被调用,得到这个容器对象之后就不会再去重新获取这个对象了,会先确定好迭代的范围,基于这个范围直接进行遍历
② 相较于普通的for循环,在每次迭代的时候都需要判断是否已到了结束边界