new和delete是用户进行动态内存申请和释放的操作符
operator new和operator delete是系统提供的全局函数
new在底层调用operator new全局函数来申请空间
delete在底层调用operator delete全局函数来释放空间
operator new和operator delete不是运算符重载函数
/*
operator new:该函数实际通过malloc来申请空间
*/
void *__CRTDECL operator new(size_t size) _THROW1(_STD bad_alloc)
{
// try to allocate size bytes
void *p;
// malloc函数在开辟失败后只是返回NULL指针
// operator new函数 封装 malloc函数
// 如果空间申请失败,进入while循环
while ((p = malloc(size)) == 0)
// 空间申请失败后的补救措施_callnewh()
// 如果补救措施失败
if (_callnewh(size) == 0)
{
// report no memory
// 这里会抛出bad_alloc类型异常
static const std::bad_alloc nomem;
_RAISE(nomem);
}
return (p);
}
/*
operator delete: 该函数最终是通过free来释放空间的
*/
void operator delete(void *pUserData)
{
_CrtMemBlockHeader * pHead;
RTCCALLBACK(_RTC_Free_hook, (pUserData, 0));
if (pUserData == NULL)
return;
_mlock(_HEAP_LOCK); /* block other threads */
__TRY
/* get a pointer to memory block header */
pHead = pHdr(pUserData);
/* verify block type */
_ASSERTE(_BLOCK_TYPE_IS_VALID(pHead->nBlockUse));
_free_dbg( pUserData, pHead->nBlockUse );
__FINALLY
_munlock(_HEAP_LOCK); /* release other threads */
__END_TRY_FINALLY
return;
}
/*
free的实现
*/
#define free(p) _free_dbg(p, _NORMAL_BLOCK)
通过底层全局函数的实现知道:
- operator new 实际也是通过malloc来申请空间,如果malloc申请空间成功就直接返回,否则执行用户提供的空间不足应对措施,如果用户提供该措施就继续申请,否则就抛出异常。
- operator delete 最终是通过free来释放空间的。
operator new与operator delete的类专属重载
针对链表的节点ListNode,通过重载类专属 operator new/operator delete实现链表节点使用内存池申请和释放内存,不需要频繁的申请/释放内存,提高代码效率。
定位new表达式(placement-new)
定位new表达式是在已分配的原始内存空间中调用构造函数初始化一个对象。
使用场景:
定位new表达式在实际中一般是配合内存池使用。因为内存池分配出的内存没有初始化,所以如果是自定义类型的对象,需要使用new的定义表达式进行显式调构造函数进行初始化。
class Date
{
public:
Date()
: _year(1)
, _month(1)
, _day(1)
{}
Date(int year, int month, int day)
:_year(year)
, _month(month)
, _day(day)
{}
private:
int _year;
int _month;
int _day;
};
int main()
{
// ptr现在指向的只不过是与Date对象相同大小的一段空间
// 还不能算是一个对象,因为没有执行-构造函数-
Date* ptr = (Date*)malloc(sizeof(Date));
// 定位new表达式
new(ptr) Date; // 无参构造函数
new(ptr) Date(2021, 2, 13); // 有参构造函数
return 0;
}