C++语言指南(十五)——动态内存

**********************************
原文链接:http://www.cplusplus.com/doc/tutorial/

**********************************

动态内存
直道现在,在我们的所有程序中,我所拥有的所有有效内存就是被我们声明的变量,在源程序中就已经确定了他们全部的大小,在程序运行之前。但是,如果我们需要一个块能在运行期才能确定大小的一个可变总的内存该怎么办呢? 例如,在我们需要一些用户的输入来决定所需内存空间的总量的情况。这个答案就是动态内存( dynamic memory ,为此 C++ 整合了操作符 new delete
<script type="text/javascript" src="http://ads.adbrite.com/mb/text_group.php?sid=170596&col=3&br=1"></script>

操作符 new new[]
为了请求动态内存我们使用操作符 new new 后面跟随一个数据类型说明符,并且——如果请求多于 1 个元素的一个序列——这些元素的个数被括在方括号 [] 中。它返回指向被分配的新内存块的开始的一个指针。它的形式为:

pointer = new type
pointer = new type [elements]

第一个表达式被用来分配包含单独一个 type 类型的元素的内存。第二个则用来分配 type 类型元素的一块内存,其中 elements 是一个整型值指出这些元素的个数。例如:
int * bobby;
bobby = new int [5];
在这种情况中,系统为 5 int 型元素动态地分配空间,并返回一个指向这个序列第一个元素的一个指针,就是被赋给 bobby 的那个。因此,现在, bobby 指向一个有效的内存块,这个内存块的空间为 5 int 类型的元素。
bobby 指向的第一个元素可以通过表达式 bobby[0] 或表达式 *bobby 来访问。它们两个是等价就像在关于指针那个节解释的。第二个元素可以使用 bobby[1] *(bobby+1) 来访问,等等……
你可能正惊讶于声明一个普通数组和给指针分配动态内存的不同,就像我们刚刚做的那样。最主要的不同是:数组的大小是一个常量值,这就限制了它的大小为我们在设计程序时决定的值,在它运行之前;反过来动态内存分配允许我们在程序执行期间(运行时)分配内存,使用任何变量或常量作为它的大小。
被我们程序请求的动态内存被系统从内存堆中分配。但是,计算机内存是一个有限的资源,它可以被耗尽。因此,有一些用来检测我们的分配内存的请求成功与否的机制是非常重要的。
C++ 提供了两种标准方法来检测分配是否成功:
一种是通过处理异常。使用这种方法,当分配失败是抛出一个 bad_alloc 类型的异常。异常是一种强大 C++ 特性,将在这个指南的稍后阐述。但是现在,你应该了解:如果这个异常被抛出,并且没有任何具体的处理者处理的话,这个程序的运行将被终止。
这个异常方法是被 new 使用的缺省方法,并且是被像这样用在一个声明中:
bobby = new int [5];  // if it fails an exception is thrown
另一种方法被称为“ nothrow (不抛) ”,当它被使用且一个内存分配失败时将发生的不是抛出一个 bad_alloc 异常或终止程序,而是 new 返回的指针是一个 null 指针,并且程序将继续运行。
这个方法可以通过使用一个特殊的叫做 nothrow 的对象作为 new 的参数来指明:
bobby = new (nothrow) int [5];
在这种情况,如果分配这块内存失败,这个失败可以通过检查是否 bobby 带有一个 null 指针值来发现:
int * bobby;
bobby = new (nothrow) int [5];
if (bobby == 0) {

 // error assigning memory. Take measures.

 };
这个 nothrow 方法比异常方法要求更多的工作,因为每一个内存分配后都必须检查返回值,但是我将在我们的例子中使用它,由于它的简单。总之这个方法对于更大的工程会变得使人讨厌,而异常方法通常更好。异常方法将在这篇指南的稍后进行详细的说明。
操作符 delete delete[]
因为对动态内存的需要通常局限在一个程序中的特定时刻,一旦它不再被需要它应该被释放,以使那块内存变的再一个对其他动态内存的请求有效。这是操作符 delete 的目的,它的形式是:
delete pointer;
delete [] pointer;
第一表达式用来删除为一个单独元素分配的内存,而第二个用来释放为一组元素分配的内存。
被作为实参传递给 delete 的必须是一个指向一个在先前由 new 分配的内存块的指针,或一个 null 指针(在 null 指针的情况中, delete 不产生任何影响)。
// rememb-o-matic
#include <iostream>
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 == 0)
    cout << "Error: memory could not be allocated" ;
 else
 {
    for (n=0; n<i; n++)
    {
      cout << "Enter number: " ;
      cin >> p[n];
    }
    cout << "You have entered: " ;
    for (n=0; n<i; n++)
      cout << p[n] << ", " ;
    delete[] p;
 }
 return 0;
}
How many numbers would you like to type? 5
Enter number : 75
Enter number : 436
Enter number : 1067
Enter number : 8
Enter number : 32
You have entered: 75, 436, 1067, 8, 32,
注意在 new 语句中方括号中的值是一个变量( i ),它的值由用户输入,而不是一个常量:
p= new (nothrow) int[i];

但是用户可能为i输入一个对于我们的系统来说太大的值,而使我们的系统无法处理它。例如,当我尝试对于问题“How many numbers(多少个数字)”给出一个10亿的值的时候,我的系统不能为这个程序分配如此多的内存,而我得到了我们为这种情况准备好的文本信息(Error:memory could be allocated)。记住:当我们尝试分配内存而没有在new表达式中指明nothrow形参的情况中,一个异常可能被抛出,如果它没有被处理将终止程序的运行。

一直检查是否一个动态内存块被成功的分配了是一个好的习惯。因此,如果你使用 nothrow 方法,你应该一直检测被返回的指针的值。否则,使用异常方法,虽然你没有处理这个异常。这样,程序将会在那一点终止,而不会继续运行那些假设一块内存已经被分配而实际上它并没有成功的代码从而引起意料不到的结果。
ANSI-C 中的动态内存
操作符 new delete 只是在 C++ 中的。它们在 C 语言中是无效的。但是使用纯 C 语言,动态内存通过函数 malloc calloc realloc free 来被使用,这些函数定义在〈 cstdlib 〉头文件中,由于 C++ C 的一个超集(这个说法不准确——译者注),这些函数在对 C++ 程序员同样是有效的。
被这些函数分配的内存块和通过 new 返回的不兼容,因此每种都需要通过它自己的那组函数或操作符来操纵。
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值