一、内存分配分类
1.从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量,static 变量。
2.在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。
3.从堆上分配,亦称动态内存分配。程序在运行的时候用malloc 或new 申请任意多少的内存,程序员自己负责在何时用free 或delete 释放内存。动态内存的生存期由程序员决定,使用非常灵活,但问题也最多。
二、传递动态内存
1.动态指针传递失败
1 #include<iostream> 2 using namespace std; 3 void GetMe(char *p,int num) 4 { 5 p=(char*)malloc(sizeof(char)*num); 6 } 7 int main() 8 { 9 char *str=NULL; 10 GetMe(str,100); 11 strcpy(str,"Hello!"); 12 cout<<str<<endl; 13 return 0; 14 }
结果:程序运行奔溃,因为str还是为NULL,往空的地址强行赋值时,内存出错
原因:str并没有获取指针p开辟的空间。本质为调用函数 GetMe 时,函数会初始化函数内的局部变量,同时为传进来的实参str(指针和值都创建,引用除外)创建一个副本 _p, _num,所以 p申请了内存,只是把p指向的内存地址改变,而str并没有改变,所以str依然没有获得内存。同时每次p申请的内存都不会得到释放,最终会造成内存泄露。
2.正确的传递动态内存
2.1 返回指针
1 #include<iostream> 2 using namespace std; 3 char* GetMe(char *p,int num) 4 { 5 p=(char*)malloc(sizeof(char)*num); 6 return p; 7 } 8 int main() 9 { 10 char *str=NULL; 11 str=GetMe(str,100); 12 strcpy(str,"Hello!"); 13 cout<<str<<endl; 14 delete str; 15 return 0; 16 }
结果:正常运行
原因:p申请了空间,并将该空间的地址作为返回值传给str,这样str就指向了p申请的内存空间
2.2 传递指针
1 #include<iostream> 2 using namespace std; 3 void GetMe(char **p,int num) 4 { 5 *p=(char*)malloc(sizeof(char)*num); 6 } 7 int main() 8 { 9 char *str=NULL; 10 GetMe(&str,100); 11 strcpy(str,"Hello!"); 12 cout<<str<<endl; 13 delete str; 14 return 0; 15 }
结果:正常运行
原因:传递了str的指针给函数GetMe(),那么p就是str的地址的副本,地址的副本指向的内存是固定,所以该函数是为str地址指向的str开辟空间
总结:实际上指针传递仍然是一种值传递,只不过在参数是指针的时候,传递的是指针的副本,这样在地址上的操作实际就反映到了内存中。
原文地址:https://www.cnblogs.com/Dana-gx/p/9741225.html
时间: 2024-11-08 08:53:20