侯捷C++内存分配课程总结二:重载new的动作
通过对operator new()的重载,修改new对内存分配时的动作
文章内容参照于侯捷 C++内存分配系列教程
文章目录
回顾:new分配内存时的动作
在知之前的文章中提到,new在被调用后,会做两到三件事,这里再复述一下:
- 为指针分配空间
- 将分配的空间的指针转型
- 调用一次创建的对象的构造函数(如果需要的话)
我们虽然要修改new在内存分配时的动作,但它的目的还是最好不要改变,也就是说,虽然我们需要修改它实现的细节,但是仍然要为它开辟一块内存空间。
一、为什么需要重载new的动作?
基于之前文章的描述,我们应该清楚一下的事情:
- new在分配内存时会调用operator new(),而operator new()又会调用malloc
- malloc分配的内存并不是所有都可以为用户所用,而是会产生一定的额外开销
所以,我们重载new的目的也很明确了:减少对malloc()的调用
而要达成的最终目标是:
- 减少内存分配空间的额外开销
2. 提高内存分配的速度
在这里我要说明,malloc本身的效率已经很高了,所以提升分配速度这一项可以说是没必要,但无论如何,减少对其的调用肯定是好的
二、重载new和new[ ]的动作
1.了解new的详细调用机制
图片来自侯捷C++内存分配课程讲义:
我们来详细分析一下这张图,从最左边的应用程序说起:
当应用程序调用new时,new会调用operator new()去分配内存。在这个时候,会有两种可能会发生的情况:
- 调用全局的std::operator new()
- 调用类私有的std::operator new()
当然,无论时是那种情况,他们的最后都会去调用malloc,同时也都可以被重载。我们现在要讨论的是,对他们的重载会发生什么情况。
我们先不去讨论new的重载,先讨论普通的函数,若在类的内部重载了一个全局的函数,那么当类的成员使用这个函数时,首先会去使用你重载的那个函数,而不是全局的。但是类以外的对象去调用这个函数的时候,依然会去调用全局的那个函数。
与之对应:
若我们重载类私有的operator new(),他只会影响这个类对new的调用
若我们重载std::operator new(),那么所有会调用new的对象都会被影响,这个影响很大
综上所述,当我们需要重载new的行为时,若不是确定的情况,请务必重载类私有的operator new()
2.重载operator new()
这里我先把重载全局的代码展现出来
inline void* operator new(size_t size)
{
//重载operatop new 改变new的行为
cout << "重载的::operator new 被调用!" << endl;
return malloc(size);//分配内存
}
inline