内存管理(一)new 和 delete 底层实现

前言

最近在看侯捷老师的内存管理这门课,整理一下课程中的知识和自己的思路。

正文

1.new

在c++的使用中,我们使用new手动申请堆区内存。下面看一下new到底干了什么。
举个例子:
Complex * pc = new Complex(1,2);
这行代码是使用new创建一个Complex型的对象。
在底层编译器实际上是完成下面的事情:

Complex *pc;
try
{ 
void* tmp = operator new(sizeof(Complex)); // 调用operator::new 分配内存
pc = static_cast<Complex*>(tmp); //转换类型
pc->Complex::Complex(1,2); // 调用构造函数(这种形式是编译器实现的形式,只有部分平台可以直接以这种形式调用构造函数)
}
catch(std::bad_alloc)
{
  // 内存分配失败就不执行构造函数
}

所以我们看到了,调用new表达式会执行两个步骤:
1.调用operator::new 分配内存
2.调用构造函数
需要注意的是,如果内存分配失败,会抛出异常,将不会调用构造函数。
那么operator::new 干了什么?

void *__CRTDECL operator new(size_t size) _THROW1(_STD bad_alloc)        
{       // try to allocate size bytes        
  void *p;
while ((p = malloc(size)) == 0)               
{
   if (_callnewh(size) == 0)                 
{  
    _THROW_NCEE(_XSTD bad_alloc, );
}

}       
   return (p);       
 }

我们看到,operator::new 实际上是调用了 malloc函数,并且如果malloc失败,会调用callnewh,如果成功,则会再malloc一次,否则抛出异常。
那么callnewh实际上就是调用new_handler(当内存分配失败时的回调函数),我们可以在函数中自己设定功能(比如释放掉一些无关紧要的内存,或结束程序等等)。当进行这些处理后如果还是分配失败,就说明真的没有内存给它分配了,就抛出异常。
可以使用_set_new_handler来设定callnewh所调用的函数。
总结
1.调用operator::new函数申请空间(operator::new 调用 malloc函数),申请失败抛出异常。
2.调用static_cast将空间的类型转换为目标类型。
3.调用构造函数(简单数据类型不需要)。

2.delete

举同一个例子:
delete pc;

pc->~Complex();
operator delete;

先是调用了对象的析构函数,然后调用operator::delete。

void operator delete(void *p)
{
 free(p);
}

由operator::delete调用free来释放内存。

总结:
1.调用对象析构函数(简单数据类型不需要)。
2.调用operator::delete函数(operator::delete 调用 free)。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值