C++11 新特性 ---- 基于范围的for循环

参考爱编程的大丙的教程和跟着老师的B站视频学习所做的笔记总结: 

c++11实用特性[c/c++项目开发必备技能][完整课程请关注公众号:爱编程的大丙]_哔哩哔哩_bilibili

基于范围的for循环 | 爱编程的大丙 (subingwen.cn)

1.C++11基于范围的for循环,语法格式:

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

declaration 表面遍历声明,在遍历过程中,当前被遍历到的元素会被存储到声明的变量中

expression 是要遍历的对象,它可以是 表达式容器数组初始化列表

基于范围的for信用循环遍历容器,示例代码如下
// 将容器中遍历的当前元素拷贝到了声明的变量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 效率要更高一些。

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 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自动推导,需要使用迭代器的方式取出元素中的键值对(和指针的操作方法相同)

  • 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 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循环,在每次迭代的时候都需要判断是否已到了结束边界

你可能感兴趣的:(c++11,新特性,c++11,新特性,基于范围的for循环,迭代,键值对)