浅析C++中的new operator
因为这几天想模拟vector,但是对C++的内存管理机制不太了解,所以近段时间一直在关注并搜索着相关信息,我会在我的博客中陆续把成果写出来,以供大家参考。
经过查阅资料,发现C++在new系统类型和用户自定义的类型时对内存的分配是不一样的。我们看下边的一段代码:
输出中的size是16,读者可能会有疑问,为什么不是12?先让我们想这么一个问题,new 和 delete 应该是成对使用的,当我们new了一个四个元素的int数组的时候,delete将要做什么工作?对,是将这16个字节(x86环境下)释放,但是,当我们new了一个用户的自定义类型的数组呢?需要释放多少个字节?不太好说,所以我们需要在新开辟的这段内存中存储相关的信息,用来保存新开辟内存的大小。
但是当我们把析构函数注释掉以后,结果又不一样了,动态申请的仅仅是12个字节,从网上搜索资料,需要多分配字节的有以下三种情况:
1 显式的声明了析构函数的
2 拥有需要调用析构函数的类的成员的
3 继承自需要调用析构函数的类的
以下摘自http://apps.hi.baidu.com/share/detail/2188389
下面运行这样一段代码做个实验:
我们直接来看VC2005下Release版本的运行结果,DEBUG版因包含了较多的调试信息,这里就不分析了:
alloc 0 bytes, address=003A36F0 distance=3815152
alloc 4 bytes, address=003A3700 distance=16
alloc 8 bytes, address=003A3710 distance=16
alloc 12 bytes, address=003A3720 distance=16
alloc 16 bytes, address=003A3738 distance=24
alloc 20 bytes, address=003A84C0 distance=19848
alloc 24 bytes, address=003A84E0 distance=32
alloc 28 bytes, address=003A8500 distance=32
alloc 32 bytes, address=003A8528 distance=40
alloc 36 bytes, address=003A8550 distance=40
每一次分配的字节数都比上一次多4,distance值记录着与上一次分配的差值,第一个差值没有实际意义,中间有一个较大的差值,可能是这块内存已经被分配了,于是也忽略它。结果中最小的差值为16字节,直到我们申请16字节时,这个差值变成了24,后面也有类似的规律,那么我们可以认为申请所得的内存结构是如下这样的:
从图中不难看出,当我们要分配一段内存时,所得的内存地址和上一次的尾地址至少要相距8个字节(在DEBUG版中还要更多),那么我们可以猜想,这8个字节中应该记录着与这段所分配的内存有关的信息。观察这8个节内的内容,得到结果如下:
图中右边为每次分配所得的地址之前8个字节的内容的16进制表示,从图中红线所表示可以看到,这8个字节中的第一个字节乘以8即得到相临两次分配时的距离,经过试验一次性分配更大的长度可知,第二个字节也是这个意义,并且代表高8位,也就说前面空的这8个字节中的前两个字节记录了一次分配内存的长度信息,后面的六个字节可能与空闲内存链表的信息有关,在翻译内存时用来提供必要的信息。这就解答了前面提出的问题,原来C/C++在分配内存时已经记录了足够充分的信息用于回收内存,只不过我们平常不关心它罢了。