【c++笔记(三)侯捷老师课程】栈,堆与内存管理

一、什么是栈(stack),什么是堆(heap)

Stack

     是存在于某作用域(scope)如大括号,的一块内存空间。例如当你调用函数,函数本身即会形成一个stack用来放置他所接收的参数,以及返回地址,以及local object。

Heap

     或成为system heap,是由操作系统提供的一块global内存空间(全局),程序可动态分配从中获得若干区域。用new的方式,有责任要delete

{
    complex c1 (1 , 2);//c1所占用的空间来自stack
    complex* p = new complex(3);
    //complex(3)是个临时对象,其所占用的空间乃是以new自heap动态分配而得,并由p指向。
    static complex c2 (1, 2);
}

上述两个对象离开作用域时(本例中为大括号),c1的生命自然消失,因为它在栈中。但是第二个对象必须手动delete。

不同对象的生命周期:

c1便是所谓的stack object,其生命在作用域(scope)结束之际结束。

这种作用域内的object,称为local object ,又称为 auto object,因为它会被“自动”清理。即析构函数会被自动调用。

c2便是所谓的static object(静态对象),其生命在作用域结束之后任然存在,直到整个程序结束。析构函数到整个程序结束才会被调用。

class complex { ... };
...
complex c3 (1, 2);

int main()
{
    ...

}

c3便是所谓global object,生命在main函数之前开始,在整个程序结束之后才结束。所谓的存在与消失,即构造函数和析构函数何时被调用。

{
    complex* p = new complex;
    ...
    delete p;

}

p所指的便是heap object,其生命在它被delete之际结束。

若没加delete p,则造成内存泄漏。

因为当作用域结束,p所指向的heap object仍然存在,但是指针p的生命却结束了,作用域之外再也看不到p(也就没机会delete p了)

new的过程:先分配memory,再调用ctor(先分配内存,再调用构造函数)

delete过程:先调用dtor,再释放memory(先调用析构函数清空指针所指的字符串那块空间(即动态分配的内存),再释放指针所占的内存)

二、宝贵的秘密

1.动态分配所得内存,在vc中的情况

在vc调试模式下,上面会多出8*4=32byte ,下面多出4byte(灰色部分),还要多出两个cookies,8byte(红色部分),一共 8+(32+4)+4*2=52。由于vc下给你的内存快一定是16的倍数,所以此时vc会给你64字节内存,所以多余的由深绿色填补。

非调试,直接运行:灰色去掉即可。8+(4*2)=16,正好是16的倍数,不需要填补。

上下cookie记录整块大小,便于系统回收时,系统知道回收多大空间

第一张图,cookie是41,对应十六进制64+1,对于程序而言是获得空间,所以是1,是malloc和free函数商量好的hhhhh。

右边两张图是字符串的动态分配内存,同理。

2.动态分配所得的数组array

 

对于左边complex来说:分配了三个complex类型的空间(灰色部分),3*8,在调试模式下,加上header,上面32,下面4(土黄色),再加上下cookie,最后,由于分配空间给的是一个数组,所以,vc给这个数组一个整数来记录数组元素个数。

一共是8*3+(32+4)+(4*2)+ 4 = 72 调整到16的倍数,是80,绿色填补。

非调试模式:去掉土黄色header

 3.array new 一定要搭配 array delete!

 

加上中括号[ ]系统才知道delete的不是一整块,而是一个数组,每个元素为指针,分别指向一块空间,唤起3次析构函数,去释放空间,而没有加中括号,系统认为删除的是一整块,也就是只唤起一次析构函数,把第一条指针所指的空间清空。

析构函数执行完毕后,才会将整块母体杀掉,即删除指针本体,但是右边这种做法导致了内存泄漏。

当然不加中括号对于不带指针的complex来说是可行的,但是为了养成好习惯,还是需要搭配使用的!

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值