学习C++数组和指针
一维数组与指针
申明了一个一维数组a[10]后,a,&a,&a[0] 都是一样,表示数组的首地址
而申明了一个指针后 p=a;后 p为数组的首地址 而&p为为指针p本身的地址
数组一旦申明后 a为常量 不能写成a++ ++a a-- 等
而指针是一个变量 可以写成 p++ ++p 等
申请多维指针时,高维数可以不指定,但是低维数必须指定
int b[][10];int c[][10][10];
int (*b2)[10]; int (*c3)[10][10];
释放: delete [] b2; delete [] c3;
数组越界
申明了一个一维数组a[10]后,第一个数为a[0],最后一个数为a[9]
a[-1]和a[10] 均越界了 但是C++不对数组越界做检查,而是按照偏移去寻址。
数组越界有时是一种攻击的手段,用来修改一些为常量的值,如对象的虚函数表的指针。
如int a[2];
const int b;//由于栈中内存分配的地址是由高到低的,并且是连续的,所以a[-1]会寻址到变量b
指针和堆的内存分配
无论什么类型的指针,WIN32下都是占用4个字节的内存空间
指针的类型代表着指针内存空间中存储的变量的类型,同时也是指针运算时的步长。
申请指针 new malloc 释放内存 delete free 必须成对使用
new int [表达式] 此表达式可以为变量
delete p是删除了p所指的目标,释放了它所占的堆空间,而不是不p本身,释放了堆空间后,p成了空悬指针,不能再通过p使用该空间,在重新给p赋值前,也不能再直接使用p
delete [] p 是删除一块连续的内存空间 漏掉[]则造成只删除p所指向的首地址所指向的空间,会造成内存释放不完全。
在函数内建立的动态对象在函数返回后还可使用,所以堆空间也称为*空间。但是由于是在堆中申请的,所以必须释放该对象所占用的堆空间,否则会造成内存泄露,并且只能释放一次。在函数体内建立动态空间,在函数体外释放很容易出错,所以不在在函数体内申请动态空间,让调用者释放。
丢失指针
指针本身是一个变量,它有自己的存储空间
指针new申请空间,是指在堆里申请一块内存,并把首地址保存到指针变量空间
指针delete,是释放堆里申请的那快空间,此时,指针的存储空间还保存着被释放的堆内存的首地址。由于指针的记忆没有清除,因此通过指针还可以访问被释放的堆空间
所以通常我们在使用完指针后,除了delete外,还要把指针变量保存的地址清空。
int *p=new int[100];
delete []p;
p=NULL;//清除指针的记忆,否则容易造成指针丢失
申请使用指针:
int *pint;
/*int i;
i=100;
pint=&i;*/
*pint=2; //不能直接对指针进行赋值,要先让其成为一个变量的地址,否则就会出现地址非法
int *p=new int;
*p=2;