C++中的指针

int *p;定义了指针变量p,这个变量储存了一个地址,地址内保存的变量是int类型的。&是取地址符,int *p = &x;就定义了一个指向整型变量x的指针变量。指向相同类型变量的指针之间可以相互赋值(不同类的不行,因为指向的地址长度可能不同)。在程序中,可以把*p看作x,例如*p = y+1;表示把y+1赋值给x,和x=y+1是完全等价的。

const int *p;表示p指向一个const int,因此*p不能修改(因为是常量),但p可以修改(因为它是一个普通的指针);int *const p = &x;(定义时就必须给出初值)表示p只能指向x*p可以修改,但p不能修改。如果是const int *const p = &x;就都不能修改。

对于暂时没有使用的指针应当赋为nullptr(这是C++11的新用法,它避免了NULL隐式转换为整型0的问题,它不能被隐式转换为整型)

指针可以进行加减运算,它基于指向的变量类型的字节数。假如p指向整型,那么p+1实际上对应着地址+4。

C++的数组名是一个指针(指针常量,不能修改指向)。a[i]本质上就是*(a+i)。如果执行p=a,那么也可以用p[i]来访问*(a+i)。定义数组与定义指针变量仅仅在内存分配上产生差别。

可以用指针申请动态内存空间。对于指针变量int *p,执行p = new int;。申请到的内存空间属于“堆”,我们的操作得到的是这片内存的首地址。在申请的时候可以顺便赋初值,p = new int(10);。也可以申请一个动态变量数组p = new int [10];(可以访问p[0]p[9])。可以顺便赋初值p = new int[5]{1,2,3,4,5};。与一般的数组不同(优点)是,数组的长度可以是变量而不一定要是常量。

动态内存空间必须手动回收。回收单个动态变量,执行delete p;。(p是指向它的指针变量)。回收数组,执行delete [] p;。回收之后,指针变量依然指向那片空间,但是无法访问。

因为堆空间有限,所以在new之前最好先确认申请成功。我们先写p = new int;,然后检查p的值。如果申请失败,p的值会被赋为nullptr

对于一个指向字符的指针变量s,可以执行s="abcde",右侧是一个字符串常量,它在内存中与静态变量储存在一起。可以访问s[3],但是不能修改s[3]

C++的函数参数只是被参数值初始化了的局部变量。然而,如果参数是指针,那么操作指针就可以改变变量的值了。因此,也可以把指针参数传入函数专门用来储存答案,这样一个函数就可以“有多个返回值”。函数中的数组参数void f(int a[])实际上只是一个指针,等价于void f(int *a),在初始化的时候将对应的指针赋给了a而已。函数的返回值也可以是一个指针,比如char *f(int a)

引用是变量的别名,定义时必须赋值int &j = i,之后在代码中j就表示i。本质上引用是一个隐式的指针,可以让我们不用写*。但引用变量的绑定是永久的,不能再执行j = &c。 引用类型可以引用引用类型,例如int &k = j,那么k,j,i就都是同一个东西。也可以引用常量const int &a = 1,实质是系统生成一个值为1的临时变量(不能修改)并让a作为这个变量的别名(一个隐式指针),也可以执行const int &a = b,那么a就不能被重新赋值,但普通变量b可以被赋值。

C++引入“引用”的目的主要是为函数的参数提供方便。在swap中定义void swap(int &a, int &b),那么调用swap(x,y)相当于给局部变量赋了初值int &a = x, &b = y,那么a,b就作为隐式指针指向了x,y,因此a,b就称为实参了。这和void swap(int *a, int *b)swap(&x, &y)是等价的,但是写起来更方便。

函数的返回值可以是引用,这相当于返回了一个变量,可以作为左值。假如有函数int &index(int j){ return a[j]; }那么就可以调用index(2) = 25。返回的引用变量不能是局部变量或者表达式,因为必须确保在调用时这个变量仍然存在。

可以定义由指针变量组成的“指针数组”,char *s[20]可以用来表示一组字符串。而由于数组名本身是一个指针,所以s本身是一个指向指针变量的指针(多级指针)。int x=15, *p = &x, **q = &p;q就是一个二级指针。

C++不能申请动态的二维数组。然而,可以先申请动态的指针数组int **a; a = new int *[3]; ... a[i] = new int [3]。回收时执行delete [] a[i]; delete [] a;

指针可以指向一个函数,double (*p)(int, int);定义了一个指向函数的指针,这个函数有两个int参数,返回类型是double(*p)的括号不能省略,不然就被当作函数原型了。假如我们已经有函数double fff(int x, int y),那么我们就可以做赋值p = fff。这样,fff(a,b)p(a,b)(*p)(a,b)就都是等价的。由于指针可以作为函数的参数,因此现在我们可以把指向函数的指针作为参数传给函数了(比如STL中sort函数的第三个参数cmp)。由于指针可以作为数组的元素,因此现在我们可以定义一个存放函数的数组,这样我们就可以方便地用数组元素(下标)来调用函数了。

(*p).a可以简写成p->a

posted @ 2022-11-11 19:53  DennyQi  阅读(67)  评论(0编辑  收藏  举报