指针如何创建动态内存?
指针如何释放所创建的动态内存?
野指针的处理办法?
在C++程序中,一些变量在整个程序中都是可见的,称为全局变量。一些只能在一个函数中可知,称为局部变量。
一个程序将操作系统分配给其运行的内存块分为4个区域:
1)代码区,存放系统的代码,即程序中的各个函数代码块。
2)全局数据区,存放程序的全局数据和静态数据。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。
3)堆区,存放程序的动态数据。程序在运行的时候用new申请任意多的内存,程序员自己负责在何时用delete释放内存。
4)栈区,存放程序的局部数据,即各个函数中的数据。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。
在C++中,申请和释放堆中分配的存贮空间,分别使用new和delete的两个运算符来完成:
例如:1、 int *pi=new int(0);
它与下列代码序列大体等价:
2、int ival=0, *pi = & ival;
区别:
pi所指向的变量是由库操作符new()分配的,位于程序的堆区中,并且该对象未命名。
new运算符返回的是一个指向所分配类型变量(对象)的指针。对所创建的变量或对象,都是通过该指针来间接操作的,而动态创建的对象本身没有名字。
在堆中建立动态一维数组
指针变量名=new 类型名[下标表达式];
注意:“下标表达式”不是常量表达式,即它的值不必在编译时确定,可以在运行时确定。
例如以下代码:
int n;
char *pc;
cout << "请输入动态数组的元素个数" << endl;
cin >> n;
pc = new char[n];
strcpy(pc, "veryGood");
cout << pc << endl;
delete[] pc;
system("pause");
在堆中释放指针所创立的内存
⑴.用初始化式(initializer)来显式初始化
int *pi=new int(0);
⑵.当pi生命周期结束时,必须释放pi所指向的目标:
delete pi;
注意这时释放了pi所指的目标的内存空间,也就是撤销了该目标,称动态内存释放(dynamic memory deallocation),但指针pi本身并没有撤销,它自己仍然存在,该指针所占内存空间并未释放,需要注意的是任何类型指针的都会占用四个字节的内存。
特别需要注意的是,如果该指针又指向了别处,那么在释放以前务必要保证指针从新指回原来的内存地址:
运行时程序会奔溃:
int *pi=new int(9);
int ival=5;
pi=&ival;
delete pi;
system(“pause”);
在堆中动态释放指针所创建的数组内存
delete [ ]指向该数组的指针变量名
注意:方括号非常重要的,如果delete语句中少了方括号,因编译器认为该指针是指向数组第一个元素的,会产生回收不彻底的问题(只回收了第一个元素所占空间),加了方括号后就转化为指向数组的指针,回收整个数组。delete [ ]的方括号中不需要填数组元素数,系统自知。即使写了,编译器也忽略。
如果指向数组的指针移动了,或者指向了别的内存地址,那么在释放前务必要将该指针回归原位,最快捷的办法是做原始内存地址的备份。
int *pi=new int[10];
int *temp = pi;
int ival = 20;
pi = &ival;
pi = temp;
delete []pi;
system(“pause”);
常见的内存错误及对策
1)内存分配未成功,却使用了它。
int *pB;
*pB=10;
解决办法:在使用内存之前检查指针是否为NULL。
assert(p!=NULL) 、if(p==NULL) 或if(p!=NULL)
2)忘记了释放内存,造成内存泄露。
含有这种错误的函数每被调用一次就丢失一块内存。
3)释放了内存却继续使用它
4)使用delete释放了内存后,没有将指针设置为NULL。导致产生“野指针”。
“野指针”不是NULL指针,是指向“垃圾”内存的指针。
如果要保存指针的内存地址,则需要使用到二级指针。
void类型的指针可以保存任何类型数据的内存地址,只不过在访问数据或者修改数据的时候,需要将指针类型转换为所保存的数据类型。
int ival = 10;
void *pv = &ival;
cout<<*(int*)pv<<endl;
在32位机器中整型与指针都占4个字节,内存的表现方式也都是二进制整数,但是整型和指针所表示的数据类型不同。无法从整型转换为整型的指针
但是整型类型被强制转换为整型指针类型后,也可以给指针赋值,这个时候要注意的是指针保存的并不是整型数据所在的内存地址。
int ival = 0x18ff00;
int *pi = (int*)ival;
cout<<pi<<endl;
cout<<*pi<<endl;
cout<<&ival<<endl;
system(“pause”);
二维数组的创建与释放
int** pii = new int*[5];
for (int i = 0; i < 5; i++)
{
*(pii+i) = new int[5];
}
for (int j = 0; j < 5; j++)
{
for (int u = 0; u < 5; u++)
{
*(*(pii + u) + j) = u;
cout << *(*(pii + u) + j);
}
cout << endl;
}
cout << sizeof(pii) << endl;
for (int v = 0; v < 5; v++)
{
delete[] pii[v];
pii[v] = NULL;
}
delete[] pii;
pii = NULL;
注意:sizeof(数组名)->数组所占内存空间;sizeof(指向数组的指针)->4