按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
数以及在函数中定义的局部变量的内存区域。帧变量通常被称作自动
变量,这是因为编译器自动为它们分配所需的内存。
帧分配有两个主要特征,首先,当我们定义一个局部变量是,编译器
将在堆栈帧上分配足够的空间来保存整个变量,对于很大的数组和其
它数据结构也是这样;其次,当超过其作用域时,帧变量将被自动的
删除。下面举一个帧分配的例子:
int Func(int Argu1;int Argu2) // 编译器将在堆栈帧上为函数参数变量分配空间
{
// 在堆栈上创建局部对象
char szDatum'256''256';
…………………………………………………………Page 148……………………………………………………………
。。。
// 超过作用域时将 自动删除在堆栈上分配的对象
}
对于局部函数变量,其作用域转变在函数退出时发生,但如果使用了
嵌套的花括号,则帧变量的作用域将有可能比函数作用域小。自动删
除这些帧变量非常之重要。对于简单的基本数据类型(如整型或字节
变量)、数组或数据结构,自动删除只是简单的回收被这些这是所占
用的内存。由于这些变量已超出其作用域,它们将再也不可以被访
问。对于C++对象,自动删除的过程要稍稍复杂一些。当一个对象被
定义为一个帧变量时,其构造函数在定义对象变量时被自动的调用,
当对象超出其作用域时,在对象所占用的内存被释放前,其析构函数
先被自动的调用。这种对构造函数和析构函数的调用看起来非常的简
便,但我们必须对它们倍加小心,尤其是对析构函数,不正确的构造
和释放对象将可能对内存管理带来严重的问题。在本书的第二章中我
们曾经历过其中的一种——指针挂起。
在帧上分配对象的最大的优越性在于这些对象将会被自动的删除,也
就是说,当你在帧上分配对象之后,不必担心它们会导致内存漏损
(memory leak)。但是,帧分配也有其不方便之处,首先,在帧上分
配的变量不可以超出其作用域,其中,帧空间往往是有限的,因此,
在很多情况下,我们更倾向于使用下面接着要讲述的堆分配来代替这
里所讲述的帧分配来为那些庞大的数据结构或对象分配内存。
堆是为程序所保留的用于内存分配的区域,它与程序代码和堆栈相隔
离。在通常情况下,C程序使用函数malloc和free来分配和释放堆内
存。调试版本 (Debug version)的MFC提供了改良版本的C++内建运算
符new和delete用于在堆内存中分配和释放对象。
使用new和delete代替malloc和free可以从类库提供的增强的内存管
理调试支持中得到好处,这在检测内存漏损时非常之有用。而当你使
用MFC的发行版本 (Release version)来创建应用程序时,MFC的发行
版本并没有使用这种改良版本的new和delete操作符,取而代之的是
一种更为有效的分配和释放内存的方法。
与帧分配不同,在堆上可分配的对象所占用的内存的总量只受限于系
统可有的所有虚拟内存空间。
以下的示例代码对比了上面讨论的内存分配方法在为数组、数据结构
和对象分配内存时的用法:
…………………………………………………………Page 149……………………………………………………………
使用帧分配为数组分配内存:
{
const int BUFF_SIZE = 128;
// 在帧上分配数组空间
char myCharArray'BUFF_SIZE';
int myIntArray'BUFF_SIZE';
// 所分配的空间在超出作用域时自动回收
}
使用堆分配为数组分配内存:
const int BUFF_SIZE = 128;
// 在堆上分配数组空间
char* myCharArray = new char'BUFF_SIZE';
int* myIntArray = new int'BUFF_SIZE';
。。。
delete '' myCharArray;
delete '' myIntArray;
使用帧分配为结构分配内存:
struct MyStructType { int topScore;};
void SomeFunc(void)
{
// 帧分配
MyStructType myStruct;
// 使用该结构
myStruct。topScore = 297;
// 在超出作用域时结构所占用的内存被自动回收
}
…………………………………………………………Page 150……………………………………………………………
使用堆分配为结构分配内存:
// 堆分配
MyStructType* myStruct = new MyStructType;
// 通过指针使用该结构
myStruct…》topScore = 297;
delete myStruct;
使用帧分配为对象分配内存:
{
CMyClass myClass; // 构造函数被自动调用
myClass。SomeMemberFunction(); // 使用该对象
}
使用堆分配为对象分配内存:
// 自动调用构造函数
CMyClass *myClass=new CMyClass;
myClass…》SomeMemberFunction(); // 使用该对象
delete myClass; // 在使用delete的过程中调用析构函数
l 注意:
l 一定要记住一个事实,在堆上分配的内存一定要记得释放,对于
使用运算符new分配的内存,应当使用delete运算符来释放;而使
用malloc函数分配的内存应当使用free函数来释放。不应 当对同
一内存块交叉使用运算符new、delete和函数malloc、free (即使
用delete运算符释放由malloc函数分配的内存,或使用free函数
释放由new运算符根本的 内存),否则在MFC的调试版本下将会导致
内存冲突。
对固定大小的内存块,使用运算符new和delete要比使用标准C库函数
malloc和free方便。但有时候我们需要使用可变大小的内存块,这
时,我们必须使用标准的C库函数malloc、realloc和free。下面的示
例代码创建了一个可变大小的数组:
…………………………………………………………Page 151……………………………………………………………
#include
#include
#define UPPER_BOUND 128
void main()
{
int *iArray=(int *)malloc(sizeof(int));
for (int i=0;i