C++中数据存储位置

C++中数据存储位置:

1.栈区:栈通常用于存储占用空间小,生命周期短的数据,如局部变量和参数变量等,需要时程序员直接声明变量使用,不需要时变量自动清除的存储区

2.堆区(动态申请内存):通过由new和malloc分配,由delete和free手动释放,或者最后程序结束时由OS释放(不负责的行为)。堆内存(动态内存)的生存期人为决定,使用灵活,缺点是分配/释放不当容易造成内存泄漏,频繁分配/释放会产生大量内存碎片。

3.全局区(静态区)static: 全局变量和静态变量的存储是在一块的,在以前的c语言中,全局变量又分为初始化(DATA段)和未初始化(BSS段)的,在c++里面没有这个区分,它们共用同一块内存区。程序结束由OS释放。

4.常量存储区:一个特殊的存储区,里面存放的是常量,不允许修改,程序结束由OS释放。非要修改可使用virtualProtoct(),改变页面属性为可写,就可以更改,但是之后要改回来

5.程序代码区:存放函数的二进制代码

int __iNum1 = 200; // 全局区 静态区
void _tmain(int argc, _TCHAR* argv[], _TCHAR** envp[])
{
int v1; // 栈区
char ch1[] = “ABC”; // 栈区,可改,如:cNum3[0]=‘a’ 可以看内存,再栈区

char* p = NULL; // 栈区
p = (char*)malloc(20); // 堆区

static int v2 = 99; // 全局静态区
char* p1 = “888888”; // 888888在常量区,cP1在栈区,不可改,必须改页面属性

TCHAR* str = _T(“HelloWorld”);
DWORD OldProtect = 0;
VirtualProtect(str, 0x1000, PAGE_READWRITE, &OldProtect); // 改页面属性
str[0] = ‘X’;
_tprintf(_T("%s\r\n"), str); // XelloWorld
VirtualProtect(str, 0x1000, OldProtect, &OldProtect); // 改回页面属性
_tprintf(_T(“Input Anykey To Exit !\r\n”));
getchar();

栈存储与堆存储的区别:

1.管理方式:a.栈由编译器自动管理,无需手动控制;b.堆则是由程序员控制,数据是用完后,一定要释放在堆中的内存,否则容易造成内存泄漏。new出来的堆内存,可由delete[] 释放

2.申请后系统的响应:a.栈存储:对于栈,只要栈的剩余空间大于所申请的空间,系统将为程序提供内存,否则将报异常,提示栈溢出。b.堆存储:对于栈,首先应该知道操作系统有一个记录空闲内存地址的链表,当系统受到程序的申请时,会遍历该链表,寻找到第一个空间大于所申请的空间的堆结点,然后将该结点从空闲结点链表中删除,并将该节点的空间分配给程序,另外,对于大多数的OS,会在这块内存空间中的首地址处记录本次分配的大小,这样,delete语句就可以正确的释放本内存的大小,系统会自动的将多余的那部分重新放入到空闲内存链表中

3.空间大小:a.栈的默认的大小为1Mb.堆的大小受限于计算机系统有效的虚拟内存,一般,32位系统下,堆内存可以到达4G的空间

4.碎片化影响:对于堆来说,频繁的使用new/delete势必造成内存空间的不连续,从而造成大量的碎片,使程序的效率降低;而栈却不会有这样的问题

5.栈、堆在地址分配方面:a.栈向着内存地址减小的方向增长(我一般认为高端地址在底下)b.堆向着内存地址增大的方向增长(我一般认为低端地址在上面)

6.分配效率:a.栈是机器系统提供的数据结构,计算机会在底层对栈提供支持: 分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的效率比较高。b.堆是由C/C++函数库提供的,它的机制很复杂,例如,分配一块内存,库函数会按照一定的算法在堆内存中搜索可用的足够大小的空间(可能内存碎片太多),就有可能调用系统功能去增加程序数据段的内存空间,这样就有机会分到足够的内存,然后进行返回。显然: 栈效率比堆效率高很多.

另外,在Windows下,最好的方式是用VirtualAlloc()分配内存,他不是在堆,也不在栈,而是直接在进程的地址空间中保留了一块内存,虽然用起来不方便,但是速度快,最灵活。堆由于大量new/delete的使用,容易造成大量的内存碎片;由于没有专门的系统支持,效率很低;由于可能引发用户态和核心态的切换,内存的申请,代价会更高。

注意:在程序中使用new运算符在堆中申请内存时,不要轻易修改指针指向的地址,因为当前指针指向了申请的堆空间的地址,如果指向其他地址,将导致内存无法释放堆空间。 如: int* data=new int[3]; int num=1; data=#这是特别容易忽视的,也是不允许的。

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值