在之前我们所写过的程序中,所必需的内存空间的大小都是在程序执行之前就已经确定了。但如果我们需要内存大小为一个变量,其数值只有在程序运行时 (runtime)才能确定,例如有些情况下我们需要根据用户输入来决定必需的内存空间,那么该怎么办呢?
答案是动态内存分配(dynamic memory),为此C++ 集成了操作符new 和delete。
1. new 和new [] 操作符
动态内存分配用操作符 new 。new 后面跟一个数据类型,如果要求的元素多于一个,需要加上 [],元素数量放在 [] 中。它返回一个指向内存块开始位置的指针。语法是:
pointer = new type
pointer = new type [number_of_elements]
第一个表达式为数据类型为 ‘type’ 的一个元素分配内存地址。第二个表达式为数据类型为 ‘type’ 的一组元素分配一块内存,其中 number_of_elements 是整数型,表示元素的个数。例如:
int* foo;
foo = new int[5];
在这个例子里,操作系统分配了可存储5个整型int元素的内存空间,返回指向这块空间开始位置的指针并将它赋给foo。因此,现在foo 指向一块可存储5个整型元素的合法的内存空间,如下图所示。
这里,foo 是一个指针,foo指向的第一个元素可以通过语句 foo[0] 或 *foo 得到,两者是等价的。第二个元素可以通过语句 foo[1] 或 *(foo+1) 得到,一次类推......
那么刚才所作的给指针分配内存空间与定义一个普通的数组有什么不同呢?最重要的不同是,一个普通数组的长度必须是一个常量,这就将它的大小在程序执行之前就被决定了。而采用动态内存分配时,数组的长度可以常量或变量,其值可以在程序执行过程中再确定 www.yztrans.com
动态内存分配通常由操作系统控制,在多任务的环境中,它可以被多个应用(applications)共享,因此内存有可能被用光。如果这种情况发生,操作系统将不能在遇到操作符new 时分配所需的内存,一个空值指针(null pointer)将被返回。
C++ 提供两种标准机制来检查内存是否分配成功:
(1)处理异常。
这种方法,当内存分配失败时,会抛出一个 bad_alloc 类型的异常。然后程序被终止。
这个方法是默认使用 new 时具有的异常方法,也就是:
foo = new int[5];
(2)使用 nothrow 。
当内存分配失败时,它不抛出异常 或 终止程序,而是被 new 返回一个空值指针,程序照常执行。
nothrow 是一个在头文件 中被声明的特殊对象,作为 new 的参数:
foo = new (nothrow) int[5];
当分配内存时,可以检查 foo 的值,若是 空值指针 null pointer 则是分配失败:
int* foo;
foo = new (nothrow)int[5];
if (foo == nullptr){//采取的措施}
2. delete 和delete[] 操作符
大部分情况下,动态分配的内存只在程序运行的具体的阶段内才有用,一旦它不再被需要,就要被释放掉,以便后面的内存分配能够使用。这就用到了delete 操作符。语法:
delete pointer;
delete []pointer;
第一种表达形式用来删除给单个元素分配的内存,第二种表达形式用来删除多元素(数组)的内存分配。在多数编译器中两种表达式等价,使用没有区别, 虽然它们实际上是两种不同的操作,需要考虑操作符重载overloading. www.tygj123.com
#include
#include //不写vs2010不会报错
using namespace std;
int main{
int i ,n;
int* p;
cout<<"How many numbers would you like to type ? "
cin>>i;
p = new (nothrow)int [i]; //根据用户输入动态分配内存
if (p == nullptr) //检查内存是否分配成功
{cout<<"Error: member could not be allocatec!"}
else
{
for(n = 0; n < i; n++)
{
cout<<"Enter number :";
cin>>p[n];
}
cout<<"You have entered :"
for(n = 0; n < i; n++)
{
cout<