看了bs的c++程序设计语言和c++编程思想中所述
c++内存还是分为三部分
通常这三部分经常被放在一块连续的物理存储单元中,但是这也是由编译器开发者决定它们的顺序
1.静态存储区域
2.栈,创建自动对象
3.堆/自由存储单元,在其上分配的内存称为动态内存分配
旧的C malloc、calloc、realloc、free
新的C++ new、delete
堆→就像在家做饭,从买菜(new)到做菜都要亲历亲为,当然最后还要洗盘子(delete),当然怎么做由你决定
堆→链表(在系统中不连接存储)
堆→内存地址低地址到高地址(受系统虚拟内存影响)
堆→快(内存)
堆→快(内存)
堆→频繁分配和释放会产生内存碎片
这种机制的特点是效率高,支持的数据有限,一般是整数,指针,浮点数等系统直接支持的数据类型,并不直接支持其他的数据结构。因为栈的这种特点,对栈的使用在程序中是非常频繁的
使用举例:
对子程序的调用就是直接利用栈完成的。机器的call指令里隐含了把返回地址推入栈,然后跳转至子程序地址的操作,而子程序中的ret指令则隐含从堆栈中弹出返回地址并跳转之的操作
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)检查