C++内存分配方式
C++内存分配方式有以下3种:
1,从静态存储区域分配。内存在程序编译的时候已经分配好了。这些内存在程序整个运行期间都存在,如全局变量,static变量等
2,在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。如数组,局部变量,形参。
3, 从堆上分配,亦称动态内存分配 。程序在运行的时候用 malloc 或 new 申请任意多少的内存,程序员自己负责在何时用 free 或 delete 释放内存。动态内存的生存期由程序员决定 ,使用非常灵活,但如果在堆上分配了空间,就有责任回收它,否则运行的程序会出现内存泄漏,频繁地分配和释放不同大小的堆空间将会产生堆内碎块。
下面一段程序输出结果是什么?
#include<iostream> using namespace std; char * GetStringA() { char str[]="Hello World!"; return str; } int main(void) { char *p=NULL; p=GetStringA(); cout<<p<<endl; getchar(); }
运行结果:
可以看出运行出来的结果不是Hello World 而是一些垃圾值,而且每次运行的结果都不一样。
原因是 char str[]="Hello World!"中 str是一个局部数组,它对应的是内存中的栈,在函数执行结束时这些存储单元自动被释放。
在函数调用时,str是一个局部数组,对应着内存中的栈:
在函数调用结束后,局部变量str被释放,p和str一样指向未知区域。
1>改正方法1:使用static变量。
#include<iostream> using namespace std; char * GetStringA() { static char str[]="Hello World!";//用static开辟一个静态存储空间 return str; } int main(void) { char *p=NULL; p=GetStringA(); cout<<"p的内容是:"<<p<<endl; getchar(); }
因为static变量从静态存储区域分配内存,这些内存在整个程序过程都存在。
输出结果:
2>改正方法2:使用全局数组。
#include<iostream> using namespace std; char * GetStringA() { char *str="Hello World!"; //让str指向字符串常量 return str; } int main(void) { char *p=NULL; p=GetStringA(); cout<<"p的内容是:"<<p<<endl; getchar(); }
str指向了一个字符串常量,可以认为是一个全局变量,从静态存储区域分配内存,保存在一个只读数据段。
3> 那么下面程序会输出什么?
#include<iostream> using namespace std; char * GetStringA() { char *str="Hello World!"; //让str指向字符串常量return str; } int main(void) { char *p=NULL; p=GetStringA(); strcpy(p,"Hello ShangHai"); cout<<"p的内容是:"<<p<<endl; getchar(); }
显然因为p指向了一个只读数据段,p指向的内存都不可以改变,运行时出错。
4>如果一定要使用strcpy()函数把Hello ShangHai复制给p呢?
实现方式1:动态内存分配或从堆上分配存储空间
#include<iostream> using namespace std; char * GetStringA() { char *str="Hello World"; return str; } int main(void) { char *p=NULL; p=GetStringA(); p=new char[100];//从堆上为p动态分配内存 strcpy(p,"Hello ShangHai"); cout<<"str的内容是:"<<p<<endl; getchar(); free(p);
p=NULL; }
实现方式2:在栈上分配内存
#include<iostream> using namespace std; int main(void) { char p[100];//在栈上分配内存 strcpy(p,"Hello ShangHai"); cout<<"str的内容是:"<<p<<endl; getchar(); }