内存管理

来源:互联网 发布:淘宝在线登录 编辑:程序博客网 时间:2024/06/05 18:47

很多人认为C/C++难于其他编程语言的关键之一就是难在内存管理上,Java可以一直new而不用去管,但是C/C++却不行,但是真正弄懂了内存的相关问题才能真正的编程。

1、内存分配方式

1.1、静态分配:在程序编译时期就已分配好,并且这块内存在程序运行期间一直存在,如全局变量、静态变量。
1.2、栈区分配:在进行函数调用时,函数的参数、函数内部的局部变量都是在内存栈区分配的,函数执行结束则在栈区分配的内存自动释放失效,栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的容量有限。
1.3、堆区分配:也称为动态内存分配,动态内存的生存期由我们自己决定,很灵活也很容易产生问题。

2、指针与数组的比较

C/C++中指针和数组在很多地方可以互相替换着用,让人产生一种错觉,以为两者等价。
数组要么在静态存储区被创建,要么在栈区被创建,数组名对应着一块内存,表示数组中第一个元素的地址,数组的地址和容量在生命期内不变,只有数组的内容可以改变。
指针可以指向任意类型的内存块,它的特点是灵活、可变,所以一般用指针来表示动态开辟的内存,指针比数组灵活,但同时也危险。

3、指针参数传递内存

如果函数的饿参数是一个指针,不要期望用该指针是申请内存。

void getMemory(char *p,int num){    p = (char*)malloc(sizeof(char)*num);}void test(){    char *str = NULL;    getMemory(str,100);     //str仍为NULL    strcpy(str,"hello");    //运行错误}

毛病出在GetMemory函数中,编译器总是要为函数的每个参数制作临时副本,指针参数p的副本是_p,编译器使_p = p。如果函数体内的程序修改了_p的内容,就导致参数p的内容做相应的修改。这就是指针可以用作输出参数的原因。在上述代码中,_p申请了新的内存,只是把_p所指的内存地址改变了,但是p丝毫未变。所以GetMemory函数并不能输出任何东西。事实上,没执行一次函数就会泄露一块内存,就是因为,没有free掉内存。

如果非要用指针参数去申请内存,可以用指向指针的指针。

void getMemory(char **p,int num){    *p = (char*)malloc(sizeof(char)*num);}void test(){    char *str = NULL;    getMemory(&str,100);     strcpy(str,"hello");        cout<<str<<endl;    free(str);}

由于指向指针的指针这个概念不易理解,可以用函数的返回值来传递动态内存。

char* getMemory(int num){    char *p = (char*)malloc(sizeof(char)*num);    return p;}void test(){    char *str = NULL;    str = getMemory(10);     strcpy(str,"hello");        cout<<str<<endl;    free(str);}

4、释放内存

free和delete都是用来释放动态内存的,它们只是把指针所指向的内存释放掉,并未把指针本身也释放掉。若释放掉所指向内存的指针不被赋值NULL的话,它就会变成“野指针”,虽然这个指针的地址不能再用,但是它仍是一个合法的指针,若程序较长,难免出错。

“野指针”是指向“垃圾”内存的指针,用if语句NULL来判断是很危险的。

5、malloc/free和new/delete的区别

malloc和free是C/C++标准库的库函数,而new/delete是C++的运算符,对于非内部数据类型的对象而言,malloc/free无法满足要求。对象在创建时要自动调用构造函数,同样对象在销毁时要自动调用析构函数。

malloc关心的是申请内存的大小,所以在使用malloc时要经常用sizeof,返回的是void*类型的指针,在使用时要强制类型转换。new则返回的是所创建对象类型的指针。

0 0
原创粉丝点击