【C++笔记】C++内存管理
- 一、C++中动态内存申请的方式
- 二、new和delete的实现原理
- 2.1、operator new和operator delete函数
一、C++中动态内存申请的方式
在C语言中我们需要动态申请空间的时候我们通常都是用malloc函数,但是malloc函数对自定义类型是没什么问题的,但是对于自定义类型就不那么适用了。
因为malloc函数负责的只是开空间,并不会去调用类的构造函数:
如果是像栈这样的有额外申请空间的类,没有初始化这将是一件很危险的事情,因为我们后面向栈中插入数据的时候就一定会出错(野指针)。
所以为了解决这样的问题,C++就设计了套新的动态内存申请的方案,即new和delete。
在C语言中使用malloc动态申请的空间不仅需要我们强转成指定的指针类型而且还需要我们手动计算空间的大小:
但在C++中使用new,我们不需要强转而且只需要给出数据的个数即可:
如果只是申请一个int空间,那就不用再int后面加[]:
并且对于自定义类型,new也会去自动调用构造函数:
像C语言一样,动态申请的空间默认不会去初始化:
但C++支持在动态申请的同时去给空间初始化:
而且也像C语言一样未指定初始化的数据就是用0来做默认值。
如果只是申请一个空间就是用括号:
这其实也就是像自定义类型一样去调用构造函数:
而如果是多个对象的话,我们就可以用到匿名对象或饮食类型转换:
而且从结果来看,如果没有指定构造的话就回去调用是用默认构造的缺省值。
说完new,我们再来说delete,对于内置类型来说new和delete与malloc和free几乎没什么区别,我们主要来说说自定义类型:
对于自定义类型,delete会去调用析构函数,这是free函数所欠缺的。
如果只是单个对象,我们我们就不用加[]:
二、new和delete的实现原理
2.1、operator new和operator delete函数
其实new和delete的底层还是使用malloc和free实现的,但他们并不能直接调用malloc和free。因为使用new如果空间申请失败的话是要抛异常的,并且delete要去调用析构函数。
而malloc如果空间申请失败的话就直接返回0了(空指针),free也只是单纯的释放空间并不会去调用析构函数。
所以C++需要对malloc和free进行“封装”,封装成两个函数:operator new和operator delete。
我们现在来看看库中的operator new和operator delete的实现:
我们会发现其实里面还是用到了malloc和free的,至于其他的那些看不懂的都是跟异常现相关的。我们现在可以不理会。