C++中内存分配方式

看了bs的c++程序设计语言和c++编程思想中所述
c++内存还是分为三部分
通常这三部分经常被放在一块连续的物理存储单元中,但是这也是由编译器开发者决定它们的顺序
1.静态存储区域
2.栈,创建自动对象
3.堆/自由存储单元,在其上分配的内存称为动态内存分配

旧的C malloc、calloc、realloc、free
新的C++ new、delete
eg:
int main()
{
	int b; //b→栈
	char s[] = "abc"; //s→栈
	char *p2; //p2→栈
	char *p3 = "123456"; //123456→常量区,p3→栈
	static int c = 0; //c→全局(静态)初始化区
	p1 = (char *)malloc(10); //p1→栈,分配得来得10字节→堆
	p2 = (char *)malloc(20); //p2→栈,分配得来得20字节→堆
	strcpy(p1, "123456"); //123456→常量区,编译器可能会将它与p3所指向的"123456"优化成一块
}

比喻

栈→就像去餐馆吃饭,只要有钱就可以点菜,不用管怎么做出的菜
堆→就像在家做饭,从买菜(new)到做菜都要亲历亲为,当然最后还要洗盘子(delete),当然怎么做由你决定

分配方式

栈→类似数据结构中的栈
堆→链表(在系统中不连接存储)

大小

栈→内存地址高地址到低地址(栈顶和栈大小确定)
堆→内存地址低地址到高地址(受系统虚拟内存影响)

申请效率

栈→较快(寄存器)
堆→快(内存)

访问效率

栈→较快(寄存器)
堆→快(内存)
eg:
char a=1;
char cStr[]="hello";
char *pStr="world";
a=cStr[1];//分别读一个字符
a=pStr[1];
	char a=1;
00411448  mov         byte ptr [ebp-9],1  
	char cStr[]="hello";
0041144C  mov         eax,dword ptr [string "hello" (416838h)]  
00411451  mov         dword ptr [ebp-1Ch],eax  
00411454  mov         cx,word ptr ds:[41683Ch]  
0041145B  mov         word ptr [ebp-18h],cx  
	char *pStr="world";
0041145F  mov         dword ptr [ebp-28h],offset string "world" (416830h)  
	a=cStr[1];
00411466  mov         al,byte ptr [ebp-1Bh]  //直接从寄存器al中读出→一步到位
00411469  mov         byte ptr [ebp-9],al  
	a=pStr[1];
0041146C  mov         eax,dword ptr [ebp-28h]  //先把ptr放入eax
0041146F  mov         cl,byte ptr [eax+1]  	   //再读出eax+1到cl中→两步
00411472  mov         byte ptr [ebp-9],cl  

碎片问题

栈→无内存碎片
堆→频繁分配和释放会产生内存碎片

栈小结

计算机中有专门的寄存器指向栈所在的地址,专门的机器指令完成数据入栈出栈的操作。
这种机制的特点是效率高,支持的数据有限,一般是整数,指针,浮点数等系统直接支持的数据类型,并不直接支持其他的数据结构。因为栈的这种特点,对栈的使用在程序中是非常频繁的
使用举例:
对子程序的调用就是直接利用栈完成的。机器的call指令里隐含了把返回地址推入栈,然后跳转至子程序地址的操作,而子程序中的ret指令则隐含从堆栈中弹出返回地址并跳转之的操作

C/C++中的自动变量是直接利用栈的例子,这也就是为什么当函数返回时,该函数的自动变量自动失效的原因

对于动态分配的内存的几个小建议

声明/定义时:
1.用malloc或new申请内存之后,应该用if(p==NULL)或if(p!=NULL)进行防错处理
2.不要忘记为数组和动态内存赋初值。防止将未被初始化的内存作为右值使用
3.避免数组或指针的下标越界,特别要当心发生"多1"或者"少1"操作
4.动态内存的申请与释放必须配对,防止内存泄漏
5.用free或delete释放了内存之后,立即将指针设置为NULL/0,防止产生"野指针"
使用时:
1.检查指针是否为NULL,防错处理
2.如果指针p是函数的参数,函数的入口处用assert(p!=NULL)检查

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值