C++编译器隐藏了代码实现,没有那么透明,java的jdk开源,比较透明,大部分实现都可以看到,Qt也是开源,具体实现我们也可以看到。
new,delete是C++动态内存分配与释放的关键字也是一种特殊的运算符,很多书籍,博客都说底层是用operator new和operator delete实现的。主要涉及到了如下四组函数:
void* operator new(size_t size);
void* operator new[](size_t size);
void operator delete(void *p);
void operator delete[](void *p);
那么他们究竟是怎么知道的呢,书籍作者可能和C++委员会成员,了解C++的实现,我们也可以从现有的代码,资料中了解一二。
下面, 我们从一个简单的程序开始来剖析C++的new与delete机制.
#include
class A
{
public:
A(int cnt)
{
m_Cnt = cnt;
}
~A()
{
}
private:
int m_Cnt;
};
int main()
{
A *a = new A(10);
if(a != NULL)
{
delete a;
a = NULL;
}
}
new的底层实现过程
我们在main代码测试,为了看new的过程,我们需要进入到汇编代码,当程序运行到new断点这一行时,右键 转到反汇编,即可查看new的过程:
在反汇编代码中可知,new动态分配内存,调用的是operator new()
我们在回到demo_01文件,在new那一行,右键【单步执行特定函数】,即可看到new的实际操作operator new的源码。
或者在反汇编文件的下方,也可以找到operator new的源码,在源码处打断点,待会儿可以跳转到那儿,如下:
void* __CRTDECL operator new(size_t const size)
{
for (;;)
{
if (void* const block = malloc(size))
{
return block;
}
if (_callnewh(size) == 0)
{
if (size == SIZE_MAX)
{
__scrt_throw_std_bad_array_new_length();
}
else
{
__scrt_throw_std_bad_alloc();
}
}
// The new handler was successful; try to allocate again...
}
}
由此可知,new还是调用malloc进行分配内存,如果malloc OK,即返回内存地址,如下所示:
可知我们new出的对象和block的地址相同
并且源码给出了new的调用过程
代码很复杂,我用的是VS2017, 这里的代码应该有C++委员会和微软的人参与,就不过多纠结了。
delete的底层实现过程
同样在delete时我们进入反汇编
单步运行特定函数
可知先执行~scalar deleting destructor, 进到A的析构函数
下面又调用了operator delete()
在该文件的下面,我们可以看到源码
右键转到源码,
就可以看到
再次单步运行
operator delete的源码
void __CRTDECL operator delete(void* const block) noexcept
{
#ifdef _DEBUG
_free_dbg(block, _UNKNOWN_BLOCK);
#else
free(block);
#endif
}
可知,delte是调用了free.
官方的delete流程
综上可知,
new ---> operator new() ---->malloc()
delete ---> operator delete() --->free()
我们也可以认为operator new和operator delete只是malloc和free的一层封装。
对于对象数组的new, delete过程和以上类似,也可以查看代码分析。