指针
1.指针是一个变量,但这个变量与普通变量最大的不同就是普通变量存储着值,而指针存储着值的地址而不是值本身。
2.一个变量的地址要怎么找到呢?这里使用地址运算符&,可以获取一个变量的地址,地址一般是一个十六进制表示的整数。
int a;
int *b = &a;//这样就可以得到变量a的地址
3.指针存储的是变量的地址,所以指针名表示地址。*运算符被称为间接值或解除引用运算符,常用于指针,得到该地址处存储的值。
int a = 100;
int *b = &a;
*b; //100
4.声明和初始化指针
int * a; //这里我们说的类型是指向int的指针(int *),也可以这么说,a是指针(地址),*a是int,而不是指针
注:把int *看成一种复合类型,是指向int的指针
5.指针的危害
指针我们可以这样理解,跟我们普通变量一样,一开始会分配一块内存空间,而普通变量在内存空间里存的是值,而指针变量在分配的内存空间里存的是另一个变量地址。在C++创建指针时,计算机就给分配了一块地址,但是这块地址中存的另一个变量的地址计算机就没有给分配。
int *a; //分配了指针变量a的内存地址,但这时还不知道这块地址里面存的是哪个变量的地址
*a =223323; //*a是指存的变量的值,而上面并没有指定是哪个变量的地址,所以223323不知道要放到什么地方,可能就会放到 我 们有用的内存区域造成数据损坏
所以在指针应用解除引用运算符(*)前,要注意看看指针是不是已经指向一个明确的地址(int *a =&b;)
6.关于不同类型的指针
int *a,b;
double *c,d;
a = &b;(注意不是*a = &b,*a是指所指向内存的值)
c = &d;
sizeof(a); //4
sizeof(c); //4 (为什么这个是4而不是8,因为c的类型不是double而是double *,指针是一个地址,所以是4)
sizeof(b); //4
sizeof(d); //8
不管是double指针还是int指针都是一个地址,4字节
7.使用new来分配内存
指针的真正用武之地在于运行阶段分配未命名的内存以存储值。在这种情况下就只能用指针来访问内存。new运算符就是在运行时来分配未命名的内存的。程序员只要告诉new需要为什么样的数据类型分配内存,new就会找到一块长度正确的内存并返回这块内存的首地址,而程序员再把这块地址赋给一个指针(变量)
如:
int *a = new int; // new int 告诉程序要适合存储int类型的内存地址,new返回一块地址的首地址赋给指针变量a
与普通指针作比较
int b;
int *a = &b;
下面这种情况除了可以用指针变量a拿到b的地址还可以用&b拿到这块内存地址,除了可以用*a拿到这块地址里存储的值,还可以直接用b拿到,而上面的情况只能用a拿到指向的内存地址,*a拿到指向地址存储的值。
注:new分配的内存块与普通变量声明分配的内存块是不一样的。普通变量存储在栈中,而new是从堆或者自由存储区的内存区域分配内存。
8.使用delect释放内存
8.1delect和new要配对使用,且delect只能释放new分配的内存(如果没有配对使用,将发生内存泄漏,即分配出去的内存将再也无法使用)
int *a = new int;
int *b =a;
delect b;
首先new分配一块内存区域,a指针指向这块内存区域,int *b = a; 声明一个指针变量b,而我们知道指针变量a其实是一个地址,将一个地址赋给指针变量b,就是让b指针也指向这块区域,使用指针a,b都指向同一块内存区域,delect b;回收这块区域,因为delect能释放new分配的内存,只要这块内存是new分配的就可以回收,使用delect b没有问题。
8.2 int * ps = new int;
delete ps;
delete释放了ps指向的内存,但是不会删除指针ps,ps还是可以重新指定一块内存区域。
9.使用new创建动态数组以及使用指针访问数组元素
9.1使用new创建动态数组
int * a = new int [10];
new返回第一个元素的地址,再把地址赋给a
同样也要配对使用delect释放这一块内存
delect [] a;
[]告诉程序要释放整个数组,而不单单只释放a指针指向的元素。
9.2操作动态数组
int *a = new int[3];
创建指针a指向包含10个int值的内存的第一个元素
这时指针就想到于一根手指。int占4个字节,a+1,表示指针移动到第二个元素,而从a到a+1所指的内存要走的就是一个int的长度,我们可以使用*a拿到第一个元素的值,*(a+1)那到第二个元素的值,*(a+2)拿到第三个元素的值。
还有另一种就是类似数组的访问方式,a[0]访问第一个元素相当于*a,a[1]访问第二个元素相当于*(a+1),a[2]访问第三个元素相当于*(a+2)
a[0] = 1;
*(a+1) = 2;
这时数组就变成了{1,2,任意值},因为第三个元素没有赋值,所以为任意值
注:*(a+1)和*a+1的区别
*的优先级高于+,*(a+1),是先把指针a向正确方向移动一个类型的长度(这里是int类型,就是4字节),到达第二个元素,再*访问该地址存储的值。而*a+1,由于优先级*a先执行,读取出当前第一个元素的值,再把值+1。