您的位置:首页 > 编程语言 > C语言/C++

C/C++学习----第四章 内存分配及其管理

2006-10-27 10:40 423 查看
[align=center]第四章 内存分配及其管理[/align]
4.1 存储
在C和C++中,有三种基本的存储使用区:
4.1.1静态存储区(Static Memory)
在静态存储区中,连接器(linker)根据程序的需求为对象分配空间。全局变量、静态类成员以及函数中的静态变量都被分配在该区域中。一个在该区域中分配的对象只被构造一次,其生存期一直维持到程序结束。在程序运行的时候其中的地址是固定不变的。在使用线程(thread,共享地址空间的并发物)的程序里,静态对象可能会引起一些问题,因为这时的静态对象是被共享的,要对其正常访问就需要进行锁定操作。
4.1.2自动存储区(Automatic Memory)
函数的参数和局部变量被分配在此。对同一个函数或区块的每一处调用,其在该区域内都有自己单独的位置。这种存储被自动创建和销毁;因而才叫做“自动存储区”。自动存储区也被称为是“在上的(be on the stack)”。
4.1.3自由存储区(Free Store)
在该区域中,程序必须明确的为对象申请空间,并可以在使用完毕之后释放申请到的空间(使用new和delete运算符)。当程序需要其中更多的空间时,就使用new向操作系统提出申请。通常情况下,自由存储区(也被称作动态存储区或者(heap))在一个程序的生存期内是不断增大的,因为其间被其它程序占用的空间从来都不被归还给操作系统。例如:
4.2 new和delete的使用
在C/C++中,允许在用户程序执行时动态的为对象分配存储。在C中,使用malloc()或calloc()、realloc()、free()来动态的分配、释放存储空间;在C++中,使用new()、delete()来动态的分配、释放存储空间。C++中的new()与C中的malloc()相比,有以下两个优点:
<1>new()自动返回正确的指针类型,不需要对返回指针进行类型转换。
int *p = newint[20];
<2> new()可以将创建的对象初始化。
int *p = newint(20);
释放内存时,无论是由malloc()还是由new一次性分配的内存空间,必须一次性释放。该内存块可以是n个连续的自定义struct空间或n个连续基本类型空间。
<3>函数中分配内存
如果非得要用指针参数去申请内存,那么应该改用“指向指针的指针”,如下所示

void GetMemory2(char **p, int num)
{
*p = new char[sizeof(char) * num];
}
void Test2(void)
{
char *str = NULL;
GetMemory2(&str, 100); // 注意参数是 &str,而不是str
strcpy(str, "hello");
cout<< str << endl;
free(str);
}
使用new创建对象数组时,不能对各个对象进行初始化。对对象数组中的每一个对象进行初始化有以下两个方法:
<1>定义专门函数来完成初始化(如下表右);
<2>在类中增加不带参数的构造函数来初始化(如下表左)。

[align=left]classpoint {[/align]
[align=left]public:[/align]
[align=left] intx, y;[/align]
[align=left] point(intox, intoy);[/align]
[align=left]point();[/align]
[align=left]};[/align]
[align=left]point::point(intox, intoy){[/align]
[align=left] x = ox;[/align]
[align=left] y = oy;[/align]
[align=left] }[/align]
[align=left]point::point(){[/align]
[align=left] x =10;[/align]
[align=left] y =10;[/align]
[align=left]}[/align]
[align=left]voidmain()[/align]
[align=left]{[/align]
[align=left] point *p1 = newpoint(3,3); //声明对象指针,创建对象并调用带参数的构造函数,初始化对象[/align]
[align=left] point *p2 = newpoint[5]; //声明对象数组指针,创建对象并调用不带参数的构造函数,初始化对象[/align]
[align=left] delete p1;[/align]
[align=left] delete []p2;[/align]
}
[align=left]Classpoint {[/align]
[align=left]Public:[/align]
[align=left] intx, y;[/align]
[align=left]voidsetPoint(int ox, int oy);[/align]
[align=left]};[/align]
[align=left]voidpoint::setPoint(int ox, int oy){[/align]
[align=left] x = ox;[/align]
[align=left] y = oy;[/align]
[align=left] }[/align]
[align=left] [/align]
[align=left]voidmain()[/align]
[align=left]{[/align]
[align=left] point *p2 = newpoint[5]; //声明对象数组指针,创建对象[/align]
[align=left] for(inti=0; i<5; i++)[/align]
[align=left] p2[i].setPoint(10, 10);//调用setPoint函数对成员变量促使化[/align]
[align=left]delete []p2;[/align]
[align=left]}[/align]
[align=left] [/align]

类的每个指针成员要么指向有效的内存,要么就指向空,在析构函数里可简单地delete,而不用担心该指针是不是被new过。
使用new()创建多维数组时,必须提供各维的大小。如:
[align=left] int (*l)[2];[/align]
l= newint[2][2]; //ok
l= newint[2][]; //error
l= newint[][2]; //error
创建两维数组,举例
[align=left]int **p = newint*[3];//首先分配指针数组中各个指针(p[0],p[1],p[2])的空间(int*型空间,非int型空间)[/align]
[align=left] for(inti = 0; i < 3; i++)[/align]
[align=left] {[/align]
[align=left] p[I] = newint [3];[/align]
[align=left] p[I][0] = 0;[/align]
[align=left] p[I][1] = 1;[/align]
[align=left] p[I][2] = 2;[/align]
[align=left] }[/align]
[align=left] for( i = 0; i < 3; i++)[/align]
[align=left] {[/align]
[align=left] delete []p[i];[/align]
[align=left] p[I] = NULL;[/align]
[align=left] }[/align]
[align=left] delete []p;[/align]
p=NULL;
[align=left]int (*l)[2]; //指向一维数组的指针[/align]
[align=left] l= newint[2][2]; [/align]
[align=left] for(i = 0; i <2;i++)[/align]
[align=left] for(intj = 0; j <2;j++)[/align]
[align=left] l[i][j] = i+j;[/align]
delete []l;
4.3 free和delete的使用
用free或delete释放了内存时,如果后面要用到指针后,应立即将指针设置为NULL,防止产生“野指针”。
4.4 重载new和delete
重载new要和重载delete匹配。
4.4.1 局部重载new和delete
重载一个与类相关的new和delete函数,只需重载运算符函数成为该类的成员函数。此时重载的new和delete仅用于该特定的类,在其他数据类型上仍然使用原始版本的new和delete。即遇到new和delete时,编译程序首先检查正在使用对象所在的类是否重载了new和delete,如果重载了,则使用这个重载版本;否则,使用全局定义的new和delete。示例如下表左部:

[align=left]classA[/align]
[align=left]{[/align]
[align=left] intx,y,z;[/align]
[align=left]public:[/align]
[align=left] A(intx1, inty1);[/align]
[align=left] ~A(){[/align]
[align=left] }[/align]
[align=left] void * operator new(unsignedintsize);[/align]
[align=left] voidoperator delete(void *p);[/align]
[align=left]};[/align]
[align=left] [/align]
[align=left]A::A(intx1, inty1)[/align]
[align=left]{[/align]
[align=left] x=x1; y=y1;[/align]
[align=left]}[/align]
[align=left]void * A::operator new (unsignedintsize)[/align]
[align=left]{[/align]
[align=left] returnmalloc(size);[/align]
[align=left] //return (void *)new char[sizeof(A)];[/align]
[align=left]}[/align]
[align=left]voidA::operator delete (void *p)[/align]
[align=left]{[/align]
[align=left] free(p);[/align]
[align=left] //delete p;[/align]
[align=left]}[/align]
[align=left] [/align]
[align=left]voidmain(void)[/align]
[align=left]{[/align]
[align=left] A *a;[/align]
[align=left] a = newA(3,10); //调用类A的重载运算符new[/align]
[align=left] deletea; //调用类A的重载运算符delete[/align]
[align=left] int *i = newint(100); //调用系统运算符new[/align]
[align=left] deletei; //调用系统运算符delete[/align]
}
[align=left]classA[/align]
[align=left]{[/align]
[align=left] intx,y,z;[/align]
[align=left]public:[/align]
[align=left] A(intx1, inty1);[/align]
[align=left] ~A(){[/align]
[align=left] }[/align]
[align=left]};[/align]
[align=left] [/align]
[align=left]A::A(intx1, inty1)[/align]
[align=left]{[/align]
[align=left] x=x1; y=y1;[/align]
[align=left]}[/align]
[align=left]void * operator new (unsignedintsize)[/align]
[align=left]{[/align]
[align=left] returnmalloc(size);[/align]
[align=left] //return (void *)newchar[size];[/align]
[align=left]}[/align]
[align=left]voidoperator delete (void *p)[/align]
[align=left]{[/align]
[align=left] free(p);[/align]
[align=left] //delete p;[/align]
[align=left]}[/align]
[align=left] [/align]
[align=left]voidmain(void)[/align]
[align=left]{ [/align]
[align=left] A *a;[/align]
[align=left] a = newA(3,10); //调用重载运算符new[/align]
[align=left] deletea; //调用重载运算符delete[/align]
[align=left] int *i = newint(100); //调用重载运算符new[/align]
[align=left] deletei; //调用重载运算符delete[/align]
}
4.4.2 全局重载new和delete
在任何类外重载new和delete,使它成为全局的。此时,C++中原来的new和delete被忽略,程序中使用重载的new和delete。示例如上表右部:
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: