• 【C++】C++ 引用详解 ⑦ ( 指针的引用 )






    一、二级指针可实现的效果



    指针的引用 效果 等同于 二级指针 , 因此这里先介绍 二级指针 ;


    使用 二级指针 作为参数 , 可以实现如下功能 :

    • 动态内存管理 : 借助二级指针 , 可以在函数中分配或释放内存 ; 如 : 创建一个动态数组或调整现有数组的大小 , 在函数中需要一个指向指针的指针作为参数 , 以便修改原始指针 ;
    void createArray(int **arr, int size) {  
        *arr = malloc(size * sizeof(int));  
    }
    
    • 1
    • 2
    • 3
    • 修改指针的值 : 借助二级指针 , 可以在函数中修改指针的值 , 即改变它所指向的地址 ; 如果直接传递 一级指针 , 函数只能修改指针指向内存中的数据 , 指针的指向不会改变 ;
    void changePointer(int **ptr) {  
        int new_value = 10;  
        *ptr = &new_value;  // 修改指针值 
    }
    
    • 1
    • 2
    • 3
    • 4
    • 传递多维数组 : C 语言中 , 数组名本质上是指向数组第一个元素的指针 , 传递多维数组到函数中通常需要传递一个指向指针的指针 , 即二级指针 ; 借助二级指针 , 函数可以修改原始数组的行指针 ;
    void process2DArray(int **array, int rows, int cols) {  
        //...  
    }
    
    • 1
    • 2
    • 3




    二、指针的引用




    1、指针的引用 等同于 二级指针 ( 重点概念 )


    普通变量的 引用 , 调用时可以直接当做 普通变量 使用 , 可实现的功能 相当于 一级指针 ;

    • 普通变量 相当于 零级指针 ;

    一级指针的 引用 , 调用时可以直接当做 一级指针 使用 , 可实现的功能 相当于 二级指针 ;

    N 级指针的 引用 , 调用时可以直接当做 N 级指针 使用 , 可实现的功能 相当于 N + 1 级指针 ;


    在 C++ 语言 中 , 使用 引用 时 , C++ 编译器 会自动将 引用 翻译为 一级指针 使用 , 自动 在 一级指针 变量 旁边加上 取地址符号 & 和 取值符号 * ;

    指针的引用 就相当于 二级指针 , 其 实现的效果 , 等同于 二级指针 ;

    C++ 编译器 遇到 指针的引用 时 , 会自动将 引用指针 转为 二级指针 ;



    2、引用本质 - 函数间接赋值简化版本


    使用函数进行间接赋值 , 需要满足如下三个条件 :

    • 函数中定义 指针类型 的 形参 , 调用函数时 修改函数外的 实参 ;
    • 将 实参 取地址 , 传递给 函数 ;
    • 在函数中 , 通过指针修改 实参的值 , 以达到修改外部变量的效果 ;

    如果将 函数 的形参类型 设置为 引用 类型 , 也能达到 间接赋值 的效果 ;

    引用 实际上是 把 间接赋值 的三个条件的后两个条件进行了合并 , C++ 编译器遇到引用 , 还是需要将 引用 还原为 C 语言中的 取地址 传入函数 , 在函数内部使用指针访问实参 ;


    3、代码示例 - 指针的引用


    该 函数 的 参数 是 一级指针的引用 , 使用该参数时 可以当做 一级指针使用 , 其效果 等同于 二级指针 ; 其效果等同于上一篇博客 【C++】C++ 引用详解 ⑥ ( 普通变量 / 一级指针 / 二级指针 做函数参数的作用 ) 中的 int getStudent(Student** stu) 函数 ;

    // 参数是 一级指针的引用 
    // 该参数 是 一级指针的引用 
    // 使用该参数时 可以当做 一级指针使用
    // 其效果 等同于 二级指针
    int getStudent(Student*& p)
    
    • 1
    • 2
    • 3
    • 4
    • 5

    调用该 一级指针 的 引用 , 可以直接访问 一级指针 , 不需要使用 * 符号 ;

    因此 这里 直接为 一级指针 进行内存分配 ;

    如果此处是二级指针 , 需要先试用 * 符号 取出二级指针指向的一级指针 , 然后再为该 一级指针 分配内存 ;

        // 为形参中声明的 Student* 指针的引用 分配内存
        // 一维指针的引用 相当于直接访问一维指针 
        // 相当于为 main 函数中的 Student* stu 变量赋值
        p = (Student*)malloc(sizeof(Student));
        // 如果传入的是二维指针参数 Student** p
        // 上述操作等同于
        // *p = (Student*)malloc(sizeof(Student));
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    代码示例 :

    // 导入标准 io 流头文件 其中定义了 std 命名空间
    #include 
    // 导入 std 命名空间
    using namespace std;
    
    struct Student
    {
        char name[64];
        int age;
    };
    
    // 参数是 指针的引用 
    // 该参数 是 一级指针的引用 
    // 使用该参数时 可以当做 一级指针使用
    // 其效果 等同于 二级指针
    int getStudent(Student*& p)
    {
        // 为形参中声明的 Student* 指针的引用 分配内存
        // 一维指针的引用 相当于直接访问一维指针 
        // 相当于为 main 函数中的 Student* stu 变量赋值
        p = (Student*)malloc(sizeof(Student));
        // 如果传入的是二维指针参数 Student** p
        // 上述操作等同于
        // *p = (Student*)malloc(sizeof(Student));
    
        if (p == NULL)
        {
            // 分配内存失败 , 返回错误码 2
            return 2;
        }
    
        // 设置结构体成员值
        p->age = 18;
    
        // 执行成功
        return 0;
    }
    
    int main() {
        // 声明 Student 对象
        Student* stu = NULL;
    
        // 调用函数 将二级指针传入函数 
        // 在函数内部创建 Student 对象
        getStudent(stu);
    
        // 打印结构体成员
        printf("stu->age = %d\n", stu->age);
    
    
        // 控制台暂停
        system("pause");
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55

    执行结果 :

    stu->age = 18
    请按任意键继续. . .
    
    • 1
    • 2

    在这里插入图片描述

  • 相关阅读:
    windows server 2012 R2的C盘空间满了,但是找不到大文件的两种原因
    LeetCode 第60天 | 84. 柱状图中最大的矩形 单调栈完结
    leetcode(力扣) 188. 买卖股票的最佳时机 IV (动态规划)
    DJ8-2 主存储器的组织
    Java core——java四种引用详解
    如何阅读 Spring Cloud OpenFein 源码
    长事务 (Long Transactions)
    攻防世界之Web_python_template_injection (web进阶)
    网上选课系统的设计与实现(ASP.NET)
    vue - vue基础/vue核心内容
  • 原文地址:https://blog.csdn.net/han1202012/article/details/132526677