C++的内存格局分为四个区:全局变量、静态数据、常量存放在全局数据区也即静态存储区,在程序编译的时候就已分配好这部分内存并存在于程序运行的整个期间;类函数成员和非成员函数代码存放在代码区;为运行函数而分配的局部变量、函数参数、返回数据、返回地址存放在栈区,开始执行函数时在栈上建立空间,结束后自动释放这些存储单元,栈内存分配运算内置在处理器的指令集中,效率高但内存空间有限;剩余空间作为堆区,在堆上进行内存分配即为动态内存分配。
处理大量数据时,因无法确定数据的确切数目,若定义尽可能大的数组长度会对内存空间造成浪费,若定义的数组长度过小会对数据处理造成影响,c++的动态内存分配可以解决这个问题,它能使程序在运行过程中按需要申请适当的内存,并在适当的地方释放,这种在程序运行过程中申请并释放的存储单元称为堆对象,申请和释放内存的过程叫做建立和删除。
一、new运算符:
new运算符的功能即为动态分配内存,使用格式如下:
(类型名*)指针变量名=new 类型名(初值);
例如:
int *pa;
pa=new int(1);
该语句在程序的运行过程中申请分配存放int类型的内存空间,并使用初值列表里的1来初始化,得到的内存空间赋值给左值为相同类型名的指针变量,即将这部分内存空间的首地址赋给了指针变量pa。
使用new运算符最常用的功能还是申请一段连续的某种数据类型的内存空间,创建该类型的数组,但数组没有名字,首地址被存放在相同基类型的指针变量中,因此可以通过指针来访问该段连续的内存。使用格式如下:
(类型名*)指针变量名=new 类型名[长度];
例如:
int *pb;
pb=new int[10];
二、delete运算符:
delete运算符的功能是释放掉new动态内存分配的内存空间,使用格式如下:
delete 指针变量名;
例如,释放上述用new得到的pa指向的内存空间:
delete pa;
若delete释放的是一段连续的内存空间,则使用格式如下:
delete []指针变量名;
例如,释放上述用new得到的pb指向的内存空间:
delete []pb;
注意:new出来的动态内存一定要delete掉,因为new分配的内存在堆上,而局部变量和函数参数分配的内存在堆栈上,由系统自动释放,而在堆上分配的内存不delete掉的话,会造成内存泄漏。
new和delete运算符的简单使用:
#include <iostream>
using namespace std;
int main(void)
{
int *pi,*ps;
float *pf;
pi=new int(1);
pf=new float(3.14);
ps=new int[5];
for(int i=0;i<5;i++)
ps[i]=i;
cout<<"*pi="<<*pi<<endl;
cout<<"*pf="<<*pf<<endl;
cout<<"*ps指向的数组元素为:"<<endl;
for(i=0;i<5;i++)
cout<<ps[i]<<" ";
cout<<endl;
delete pi;
delete pf;
delete []ps;
return 0;
}
运行结果为:
*pi=1
*pf=3.14
*ps指向的数组元素为:
0 1 2 3 4
下面来讲一下动态数组的两个小问题。
一、sizeof可以测试整型一维数组的长度吗?
答案是不能,因为,sizeof是编译期运行的,而动态内存分配是在程序运行过程中申请并释放存储单元,动态申请的数组是无法使用此方法测出长度的。
要想知道动态数组的长度只能是在new数组的时候记录下它的长度。
int size;
cin>>size;
int exp=new int[size];
此时的size+1即为动态数组的长度。
二、动态申请二维数组时应该注意什么?
引例:
int a;
cin>>a;
double (*pa)=new double[5][a];
这里就会出现错误,原因很简单,众所周知二维数组中第二个数组的参数必须要确定,而第一维可以省略,因为可以通过第二维来计算第一维,同理动态数组中第二维必须是确定的,因为创建之后,p1指向一个内存地址,p2也指向一个内存地址,第二维大小若不知道,系统就不知道p2的指向了。因此上面的第三条语句应该改成:
double (*pa)=new double[a][5];
如有问题欢迎留言讨论