「Cpp」引用和指针


序言

本文介绍C++中引用指针const限定符常量表达式等几个部分的内容。对应原书45页——60页

引用

引用为对象起了另外一个名字,引用类型可以引用另外一种类型。通常情况下可以将声明符写成&d的形式来定义引用类型,其中d是声明的变量名。

  • 举例如下
    int a = 16;
    int &b = a; //b是a的引用,需要在b前加引用符&
    int &c;     //错误,没有初始化!!!
  • 引用的实质:引用并不是对象,而是对象的一个新名字,所有对引用的操作实际是都是在对源对象进行操作
  • 引用的定义:允许在一行中定义多个引用但是每个引用前必须有&限定,例如
    int a = 1, b = 2;
    int &c = a, &d = b;

指针

指针是“指向”另外一种类型的复合类型,可以像引用一样实现对其他对象的间接引用。但是它有两点和引用不同——
- 指针本身是对象,可以对指针本身进行赋值和访问,而且可以在指针的生命周期内先后指向不同的对象
- 指针在定义的时候无需赋初值。和其他类型相似,如果在快作用域中的指针没有被初始化,则会拥有一个不确定的值。

指针基础知识

  1. 举例如下

    //指针定义
    int a = 1;
    int *b = &a;  //用取地址符&取得a的地址,并将地址赋值给b
    int *c = b;   //此时b和c其实是一样的
      
    //用指针访问对象(仅适用于有效指针)
    cout << *b;   //用解引用符*得到原指针指向的对象的值
    *b = 0x7fff;  //此时a的值被赋成0x7fff

  2. 指针的定义:允许一行对多个指针类型进行声明和定义

    int a = 1, b = 2;
    int *c = &a, *d = &b;

  3. 空指针

    • 一般要用nullptr进行初始化
    • 空指针不能使用解引用符进行解引用
  4. 关于void

    • void是一种比较特殊的指针类型,可以指向任意对象,存放任意对象的地址,但是也仅限于存放,不能进行访问,也不可以直接操作void*所指的对象。
    • void可以做的事: 和其他指针进行比较作为函数的输入和输出或者赋值给另外一个void*指针
  5. 指向指针的指针

    int a = 1;
    int *b = &a;    //b指向的是“int型”
    int **c = &b;   //c指向的是“指向int的指针”

  6. 对指针的引用

    int i = 1;
    int *p = &i;
    int *&r = p;

指针数组和数组指针

  1. 基本解释(参考这篇博客)

    指针数组:指针数组可以说成是”指针的数组”,首先这个变量是一个数组,其次,”指针”修饰这个数组,意思是说这个数组的所有元素都是指针类型,在32位系统中,指针占四个字节。

    数组指针:数组指针可以说成是”数组的指针”,首先这个变量是一个指针,其次,”数组”修饰这个指针,意思是说这个指针存放着一个数组的首地址,或者说这个指针指向一个数组的首地址。`

  2. 指针数组

    • 指针数组的定义
      char *a = {"red", "blue", "green"};
    • 函数形参使用指针数组
      //first method
      int function(char *a[]){
      //...
      }
      //second method
      int function(char **a){
      	//...
      }
  3. 数组指针

    • 数组指针的定义(注意此时是(*p))
      int a[5][4] = {0};
      int (*p1)[4] = a;
      int (*p2)[4] = &a[0]; //p1和p2都是指向二维数组a的首地址
    • 函数形参使用二维数组可用数组指针
      void f1(a[][4]){
      	//...
      }
      void f2((*p)[4]){
      	//...
      }
      int main(){
                int a[5][4];
                f1(a);
                f2(a);
                return 0
      }

      ### 指针函数,函数指针和函数指针数组
  4. 指针函数

    • 定义:指针函数就是返回指针值的函数,本质是一个函数。所以指针函数等价于“返回值为指针的函数”
    • 用法:
      int *GetNum(int x); //指针函数声明形式

      由此可以看出,指针函数的本质仍然是函数,可以把它当作一般函数来声明和使用。
  5. 函数指针

    • 定义:函数指针就是一个指向函数的指针。每个函数在编译时,会被分配一个入口地址,一般用函数名来表示,这个地址就是该函数的指针。
    • 用法1:(基础用法)
      int max(int a, int b) {
          return a>b ? a : b;
      }
      
      int main()
      {
          int(*func)(int, int);       //定义一个指向该函数形式的指针变量
          func = max;
          cout << func(1, 2) << endl;
          return 0;
      }
    • 用法2:(typedef)
      typedef int(*func)(int, int);
      
      int max(int a, int b) {
          return a>b ? a : b;
      }
      
      void main(void){
          func newfunc = max;
          cout << newfunc(1, 2) << endl;
          return 0;
      }
  6. 函数指针数组

    • 定义:顾名思义,就是每个元素都是函数指针的数组,直接在函数指针名后面加上数组符号[ ]即可。
    • 用法
      void f1(){
          cout << "f1" << endl;
      }
      void f2(){
          cout << "f2" << endl;
      }
      void f3(){
          cout << "f3" << endl;
      }
      int main()
      {
          //定义三个函数指针
          void(*pf1)() = &f1;
          void(*pf2)() = &f2;
          void(*pf3)() = &f3;
          //接下来就是定义一个数组把他们三个装进去。
          void(*pfarr[3])();
          void(*pfunarr[3])();
          pfunarr[0] = pfun;
          pfunarr[1] = pfun2;
          pfunarr[2] = pfun3;
          /*  或者这样赋值
          pfunarr[0] = &fun1;
          pfunarr[1] = &fun2;
          pfunarr[2] = &fun3;
          */
          pfunarr[0]();
          pfunarr[1]();
          pfunarr[2]();
          /*  或者这样调用
          (*pfunarr[0])();
          (*pfunarr[1])();
          (*pfunarr[2])();
      }

      从上述代码中也可以看出来,函数名实际上就是函数地址,这一点与数组有异曲同工之妙。

文章作者: Hyggge
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Hyggge !
  目录