new delete operator new oprator delete operator new[] operator delete[] 详解
来源:互联网 发布:淘宝秋水兰熙旗舰店 编辑:程序博客网 时间:2024/06/05 22:45
在vs2015里,有这么一个文件 vcruntime_new.h
内容大致如下:
内容大致如下:
#define __CRTDECL __cdecl
namespace std
{
struct nothrow_t { };
{
struct nothrow_t { };
extern nothrow_t const nothrow;
}
_Ret_notnull_ void* operator new[](
size_t _Size
);
_Ret_notnull_ void* operator new(
size_t _Size
);
_Ret_maybenull_ void* operator new[](
size_t _Size,
std::nothrow_t const&
) throw();
_Ret_maybenull_ void* operator new(
size_t _Size,
std::nothrow_t const&
) throw();
void __CRTDECL operator delete(
void* _Block
) throw();
}
_Ret_notnull_ void* operator new[](
size_t _Size
);
_Ret_notnull_ void* operator new(
size_t _Size
);
_Ret_maybenull_ void* operator new[](
size_t _Size,
std::nothrow_t const&
) throw();
_Ret_maybenull_ void* operator new(
size_t _Size,
std::nothrow_t const&
) throw();
void __CRTDECL operator delete(
void* _Block
) throw();
void __CRTDECL operator delete(
void* _Block,
std::nothrow_t const&
) throw();
void* _Block,
std::nothrow_t const&
) throw();
void __CRTDECL operator delete[](
void* _Block
) throw();
void* _Block
) throw();
void __CRTDECL operator delete[](
void* _Block,
std::nothrow_t const&
) throw();
void* _Block,
std::nothrow_t const&
) throw();
void __CRTDECL operator delete(
void* _Block,
size_t _Size
) throw();
void* _Block,
size_t _Size
) throw();
void __CRTDECL operator delete[](
void* _Block,
size_t _Size
) throw();
void* _Block,
size_t _Size
) throw();
#ifndef __PLACEMENT_NEW_INLINE
#define __PLACEMENT_NEW_INLINE
_Ret_notnull_
inline void* __CRTDECL operator new(size_t _Size, void* _Where) throw()
{
(void)_Size;
return _Where;
}
#define __PLACEMENT_NEW_INLINE
_Ret_notnull_
inline void* __CRTDECL operator new(size_t _Size, void* _Where) throw()
{
(void)_Size;
return _Where;
}
inline void __CRTDECL operator delete(void*, void*) throw()
{
return;
}
{
return;
}
_Ret_notnull_
inline void* __CRTDECL operator new[](size_t _Size,void* _Where) throw()
{
(void)_Size;
return _Where;
}
inline void* __CRTDECL operator new[](size_t _Size,void* _Where) throw()
{
(void)_Size;
return _Where;
}
inline void __CRTDECL operator delete[](void*, void*) throw()
{
}
{
}
_Ret_maybenull_ 告诉你 null maybe 不知道想表达什么??
_Ret_notnull_ 告诉你返回值为非 null
throw() 告诉你这个函数不抛出异常
我们先来分析一下分配内存的函数,这两个函数在分配失败时,抛出bad_alloc异常。
通过调试追踪,两个函数的实现如下:
通过调试追踪,两个函数的实现如下:
#define SIZE_MAX 0FFFFFFFFh
void* __CRTDECL operator new[](size_t const size) //new_array.cpp
{
return operator new(size);
}
{
return operator new(size);
}
void* __CRTDECL operator new(size_t const size) //new_scalar.cpp
{
for (;;)
{
if (void* const block = malloc(size))
{
return block;
}
{
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();
}
}
{
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...
}
}
}
}
msdn:
int _callnewh(
size_t size
)
_callnewh 调用当前已经安装的 “new handler” (函数,通过set_new_handle 设置)
参数 size: new operator 尝试去分配的内存数量
返回值:
失败,返回0,没有"new handler"安装 或者 没有"new handler"处于活跃状态
成功,返回1,“new handler"已经安装并处于活跃状态。内存分配可以重试
异常:此函数将抛出 bad_alloc异常,如果不能找到 "new handler"(已经安装)
备注:如果new 运算符无法成功分配内存,"new handle"函数可以启动一些适当的操作。
如释放内存,以便后续分配成功。
ok,_callnewh和_set_new_handler相关,具体怎样, msdn 有具体的例子,很容易理解。
ok,通过以下代码的调试跟踪:
#include <stdio.h>
#include <new.h>
void main()
{
void* pVoid = ::operator new(SIZE_MAX);
}
我发现:_callnewh返回了0。所以我们得
看看vs在void main函数之前是否插入了安装"new handler"函数的代码
#include <stdio.h>
#include <new.h>
void main()
{
_PNH pnh = _set_new_handler(0);
printf("%d\n",(int)pnh);
}
输出 0,说明没有安装
int _callnewh(
size_t size
)
_callnewh 调用当前已经安装的 “new handler” (函数,通过set_new_handle 设置)
参数 size: new operator 尝试去分配的内存数量
返回值:
失败,返回0,没有"new handler"安装 或者 没有"new handler"处于活跃状态
成功,返回1,“new handler"已经安装并处于活跃状态。内存分配可以重试
异常:此函数将抛出 bad_alloc异常,如果不能找到 "new handler"(已经安装)
备注:如果new 运算符无法成功分配内存,"new handle"函数可以启动一些适当的操作。
如释放内存,以便后续分配成功。
ok,_callnewh和_set_new_handler相关,具体怎样, msdn 有具体的例子,很容易理解。
ok,通过以下代码的调试跟踪:
#include <stdio.h>
#include <new.h>
void main()
{
void* pVoid = ::operator new(SIZE_MAX);
}
我发现:_callnewh返回了0。所以我们得
看看vs在void main函数之前是否插入了安装"new handler"函数的代码
#include <stdio.h>
#include <new.h>
void main()
{
_PNH pnh = _set_new_handler(0);
printf("%d\n",(int)pnh);
}
输出 0,说明没有安装
ok,这就很好理解了。如果在我们调用 operator new 之前,都没有调用_set_new_handle,
去安装 处理函数(比如释放内存啊)去处理malloc 失败,那么 _callnewh函数将返回0,
接着就是处理 size 是否等于 SIZE_MAX(在这里 SIZE_MAX == 0x0FFFFFFFF),如果是则抛出
bad_array_new_length 异常,否则抛出 bad_alloc异常.
去安装 处理函数(比如释放内存啊)去处理malloc 失败,那么 _callnewh函数将返回0,
接着就是处理 size 是否等于 SIZE_MAX(在这里 SIZE_MAX == 0x0FFFFFFFF),如果是则抛出
bad_array_new_length 异常,否则抛出 bad_alloc异常.
所以 operator new(size_t Size) 分配失败是抛出异常的。
所以下面这样写代码是错误的:
#include <stdio.h>
#include <new.h>
void main()
{
void* pVoid = ::operator new(SIZE_MAX); //抛出异常
if(pVoid == nullptr) //永远也执行不到这里
printf("opeartor new faile\n");
}
#include <stdio.h>
#include <new.h>
void main()
{
try
{
void* pVoid = ::operator new(SIZE_MAX);
}catch(bad_alloc &ba) //bad_array_new_length是bad_alloc的子类
{
printf("%s\n",ba.what());
}
}
#include <stdio.h>
#include <new.h>
void main()
{
void* pVoid = ::operator new(SIZE_MAX); //抛出异常
if(pVoid == nullptr) //永远也执行不到这里
printf("opeartor new faile\n");
}
#include <stdio.h>
#include <new.h>
void main()
{
try
{
void* pVoid = ::operator new(SIZE_MAX);
}catch(bad_alloc &ba) //bad_array_new_length是bad_alloc的子类
{
printf("%s\n",ba.what());
}
}
ok ! 顺便贴一下相关的异常类源码,便于以后阅读:
//这两函数是导入函数,从exception,来看,这两个函数是分配内存,和销毁内存,
//因为std::exception 是处理内存无法分配的异常,所以,他的内存分配机制肯定
//不同,源码没有公布出来。
__declspec(dllimport) void __cdecl __std_exception_copy(
_In_ __std_exception_data const* _From,
_Out_ __std_exception_data* _To
);
__declspec(dllimport) void __cdecl __std_exception_destroy(
_Inout_ __std_exception_data* _Data
);
///
/////////////// vcruntime_exception.h start///////////////
struct __std_exception_data
{
char const* _What;
bool _DoFree;
};
_Inout_ __std_exception_data* _Data
);
///
/////////////// vcruntime_exception.h start///////////////
struct __std_exception_data
{
char const* _What;
bool _DoFree;
};
namespace std {
class exception
{
public:
exception() throw()
: _Data()
{
}
{
public:
exception() throw()
: _Data()
{
}
explicit exception(char const* const _Message) throw()
: _Data()
{
__std_exception_data _InitData = { _Message, true };
__std_exception_copy(&_InitData, &_Data);
}
: _Data()
{
__std_exception_data _InitData = { _Message, true };
__std_exception_copy(&_InitData, &_Data);
}
exception(char const* const _Message, int) throw()
: _Data()
{
_Data._What = _Message;
}
: _Data()
{
_Data._What = _Message;
}
exception(exception const& _Other) throw()
: _Data()
{
__std_exception_copy(&_Other._Data, &_Data);
}
: _Data()
{
__std_exception_copy(&_Other._Data, &_Data);
}
exception& operator=(exception const& _Other) throw()
{
if (this == &_Other)
{
return *this;
}
__std_exception_destroy(&_Data);
__std_exception_copy(&_Other._Data, &_Data);
return *this;
}
{
if (this == &_Other)
{
return *this;
}
__std_exception_destroy(&_Data);
__std_exception_copy(&_Other._Data, &_Data);
return *this;
}
virtual ~exception() throw()
{
__std_exception_destroy(&_Data);
}
{
__std_exception_destroy(&_Data);
}
virtual char const* what() const
{
return _Data._What ? _Data._What : "Unknown exception";
}
private:
__std_exception_data _Data;
};
{
return _Data._What ? _Data._What : "Unknown exception";
}
private:
__std_exception_data _Data;
};
class bad_exception
: public exception
{
public:
bad_exception() throw()
: exception("bad exception", 1)
{
}
};
: public exception
{
public:
bad_exception() throw()
: exception("bad exception", 1)
{
}
};
class bad_alloc
: public exception
{
public:
bad_alloc() throw()
: exception("bad allocation", 1)
{
}
private:
friend class bad_array_new_length;
: public exception
{
public:
bad_alloc() throw()
: exception("bad allocation", 1)
{
}
private:
friend class bad_array_new_length;
bad_alloc(char const* const _Message) throw()
: exception(_Message, 1)
{
}
};
: exception(_Message, 1)
{
}
};
class bad_array_new_length
: public bad_alloc
{
public:
: public bad_alloc
{
public:
bad_array_new_length() throw()
: bad_alloc("bad array new length")
{
}
};
}
/////////////// vcruntime_exception.h end///////////////
: bad_alloc("bad array new length")
{
}
};
}
/////////////// vcruntime_exception.h end///////////////
ok ,看源码,就很容易理解了。
现在我们来看一下,另外两个能分配内存的函数,这两个函数
分配失败时,返回nullptr ,不抛出异常.
分配失败时,返回nullptr ,不抛出异常.
//new_array_nothrow.cpp
void* __CRTDECL operator new[](size_t const size, std::nothrow_t const& x) noexcept
{
return operator new(size, x);
}
void* __CRTDECL operator new[](size_t const size, std::nothrow_t const& x) noexcept
{
return operator new(size, x);
}
//new_scalar_nothrow.cpp
void* __CRTDECL operator new(size_t const size, std::nothrow_t const&) noexcept
{
try
{
return operator new(size);
}
catch (...)
{
return nullptr;
}
}
void* __CRTDECL operator new(size_t const size, std::nothrow_t const&) noexcept
{
try
{
return operator new(size);
}
catch (...)
{
return nullptr;
}
}
相当简单,他们最终调用的是 operator new(size_t _Size),
然后捕获 operator new(size_t _Size)异常,
如果 operator new(size_t _Size)分配失败,返回 nullptr;
然后捕获 operator new(size_t _Size)异常,
如果 operator new(size_t _Size)分配失败,返回 nullptr;
ok! 现在来分析删除操作的函数
//delete_scalar.cpp
void __CRTDECL operator delete(void* const block) noexcept
{
#ifdef _DEBUG
_free_dbg(block, _UNKNOWN_BLOCK);
#else
free(block); //release版本,直接调用 free ,非常简单
#endif
}
//delete_scalar.cpp
void __CRTDECL operator delete(void* const block) noexcept
{
#ifdef _DEBUG
_free_dbg(block, _UNKNOWN_BLOCK);
#else
free(block); //release版本,直接调用 free ,非常简单
#endif
}
//delete_scalar_size.cpp
void __CRTDECL operator delete(void* block, size_t) noexcept
{
operator delete(block);
}
void __CRTDECL operator delete(
void* _Block,
std::nothrow_t const&
) throw(); //并未实现,直接调用 opeartor delete(void* block,size_t)
void __CRTDECL operator delete(void* block, size_t) noexcept
{
operator delete(block);
}
void __CRTDECL operator delete(
void* _Block,
std::nothrow_t const&
) throw(); //并未实现,直接调用 opeartor delete(void* block,size_t)
//delete_array.cpp
void __CRTDECL operator delete[](void* block) noexcept
{
operator delete(block);
}
void __CRTDECL operator delete[](void* block) noexcept
{
operator delete(block);
}
//delete_array_size.cpp
void __CRTDECL operator delete[](void* block, size_t) noexcept
{
operator delete[](block);
}
void __CRTDECL operator delete[](void* block, size_t) noexcept
{
operator delete[](block);
}
//delete_array_nothrow.cpp
void __CRTDECL operator delete[](void* block, std::nothrow_t const&) noexcept
{
operator delete[](block);
}
void __CRTDECL operator delete[](void* block, std::nothrow_t const&) noexcept
{
operator delete[](block);
}
很简单,最终调用的都是free函数,出现那么多 operator delete 的重载函数,主要
是与 operator new 对应。
是与 operator new 对应。
operator new delete new[] delete[] 是可以重载的。
那就纳闷了, new delete 不是会调用构造函数,虚构函数吗? new X[size] 不是要用 delete[] 来释放吗
楼主,你分析有误吧。怎么没看到构造函数,虚构函数的调用,怎么 delete[] delete 都只是调用了free.
嗯,其实 new delete new X[size] delete[] 是编译器的关键字,只有少部分的人能改变他的操作方式。
我用的是VS,所以只有VS的编写者,能改变。
而 operator new delete new[] delete[] 注意" operator " ,只负责如何去分配内存。所以我们是可以
通过重载来改变的。
楼主,你分析有误吧。怎么没看到构造函数,虚构函数的调用,怎么 delete[] delete 都只是调用了free.
嗯,其实 new delete new X[size] delete[] 是编译器的关键字,只有少部分的人能改变他的操作方式。
我用的是VS,所以只有VS的编写者,能改变。
而 operator new delete new[] delete[] 注意" operator " ,只负责如何去分配内存。所以我们是可以
通过重载来改变的。
我们通过反汇编来,区分它们的区别
#include <stdio.h>
#include <new.h>
#include <stdio.h>
#include <new.h>
class testClass
{
public:
testClass(int iValue = 0)
{
m_iValue = iValue;
printf("testClass::testClass()\n");
}
{
public:
testClass(int iValue = 0)
{
m_iValue = iValue;
printf("testClass::testClass()\n");
}
~testClass()
{
printf("testClass::~testClass()\n");
}
{
printf("testClass::~testClass()\n");
}
void testFunc()
{
printf("testClass::testFunc() m_iValue = %d\n", m_iValue);
}
{
printf("testClass::testFunc() m_iValue = %d\n", m_iValue);
}
private:
int m_iValue;
};
int m_iValue;
};
void main()
{
testClass* ptc = new testClass(1);
testClass* ptc1 = (testClass*)::operator new(sizeof(testClass));
delete ptc;
::operator delete(ptc1);
}
{
testClass* ptc = new testClass(1);
testClass* ptc1 = (testClass*)::operator new(sizeof(testClass));
delete ptc;
::operator delete(ptc1);
}
看一下反汇编代码:
testClass* ptc = new testClass(1);
//调用 operator new(size_t _Size) 分配内存
00A91076 push 4
00A91078 call operator new (0A910CFh)
//调用 testClass::testClass(int) 构造函数
00A9107D mov edi,eax
00A9107F push offset string "testClass::testClass()\n" (0A92190h)
00A91084 mov dword ptr [ebp-4],edi
00A91087 mov dword ptr [edi],1
00A9108D call printf (0A91040h)
testClass* ptc = new testClass(1);
//调用 operator new(size_t _Size) 分配内存
00A91076 push 4
00A91078 call operator new (0A910CFh)
//调用 testClass::testClass(int) 构造函数
00A9107D mov edi,eax
00A9107F push offset string "testClass::testClass()\n" (0A92190h)
00A91084 mov dword ptr [ebp-4],edi
00A91087 mov dword ptr [edi],1
00A9108D call printf (0A91040h)
testClass* ptc1 = (testClass*)::operator new(sizeof(testClass));
//调用 operator new(size_t _Size) 分配内存
00A91092 push 4
00A91094 call operator new (0A910CFh)
delete ptc;
//调用 testClass::~testClass() 析构函数
00A91099 push offset string "testClass::~testClass()\n" (0A921A8h)
00A9109E mov esi,eax
00A910A0 call printf (0A91040h)
// 调用 operator delete(void* block,size_t Size) 释放内存
00A910A5 push 4
00A910A7 push edi //edi 为 ptc
00A910A8 call operator delete (0A9136Ah)
::operator delete(ptc1);
//调用 operator delete(void* bolck) 释放内存
00A910AD push esi // esi 为ptc1
00A910AE call operator delete (0A91378h)
00A910B3 add esp,1Ch
//调用 operator new(size_t _Size) 分配内存
00A91092 push 4
00A91094 call operator new (0A910CFh)
delete ptc;
//调用 testClass::~testClass() 析构函数
00A91099 push offset string "testClass::~testClass()\n" (0A921A8h)
00A9109E mov esi,eax
00A910A0 call printf (0A91040h)
// 调用 operator delete(void* block,size_t Size) 释放内存
00A910A5 push 4
00A910A7 push edi //edi 为 ptc
00A910A8 call operator delete (0A9136Ah)
::operator delete(ptc1);
//调用 operator delete(void* bolck) 释放内存
00A910AD push esi // esi 为ptc1
00A910AE call operator delete (0A91378h)
00A910B3 add esp,1Ch
operator delete(void* block) 和 operator delete(void* block,size_t size) 最终都调用free 没什么区别
很容易理解。
很容易理解。
void main()
{
testClass* ptc_a = new testClass[6];
testClass* ptc1_a = (testClass*)::operator new[](sizeof(testClass)*6);
delete[] ptc_a;
::operator delete[](ptc1_a);
}
反汇编:
testClass* ptc_a = new testClass[6];
//调用 operator new[](size_t size) --> operator new(size_t size) 分配内存
003810A6 push 1Ch //编译器计算所得内存大小 sizeof(testClass)*6 = 4*6 = 24 = 18h
// 18h + 4(保存数组个数 6) = 1ch
003810A8 call operator new[] (0381506h)
003810AD add esp,4
//调用testClass::testClass() 构造函数 (循环6次)
003810B0 mov dword ptr [ebp-10h],eax
003810B3 mov dword ptr [ebp-4],0
003810BA test eax,eax
003810BC je main+5Dh (03810DDh)
003810BE push offset testClass::~testClass (0381070h)
003810C3 push offset testClass::`default constructor closure' (0381140h)
003810C8 push 6 //循环6次
003810CA lea edi,[eax+4]
003810CD mov dword ptr [eax],6 //保存数组个数
003810D3 push 4
003810D5 push edi
003810D6 call `eh vector constructor iterator' (038150Fh)
003810DB jmp main+5Fh (03810DFh)
003810DD xor edi,edi
{
testClass* ptc_a = new testClass[6];
testClass* ptc1_a = (testClass*)::operator new[](sizeof(testClass)*6);
delete[] ptc_a;
::operator delete[](ptc1_a);
}
反汇编:
testClass* ptc_a = new testClass[6];
//调用 operator new[](size_t size) --> operator new(size_t size) 分配内存
003810A6 push 1Ch //编译器计算所得内存大小 sizeof(testClass)*6 = 4*6 = 24 = 18h
// 18h + 4(保存数组个数 6) = 1ch
003810A8 call operator new[] (0381506h)
003810AD add esp,4
//调用testClass::testClass() 构造函数 (循环6次)
003810B0 mov dword ptr [ebp-10h],eax
003810B3 mov dword ptr [ebp-4],0
003810BA test eax,eax
003810BC je main+5Dh (03810DDh)
003810BE push offset testClass::~testClass (0381070h)
003810C3 push offset testClass::`default constructor closure' (0381140h)
003810C8 push 6 //循环6次
003810CA lea edi,[eax+4]
003810CD mov dword ptr [eax],6 //保存数组个数
003810D3 push 4
003810D5 push edi
003810D6 call `eh vector constructor iterator' (038150Fh)
003810DB jmp main+5Fh (03810DFh)
003810DD xor edi,edi
testClass* ptc1_a = (testClass*)::operator new[](sizeof(testClass)*6);
//调用 operator new[](size_t size) 分配内存
003810DF push 18h //sizeof(testClass)*6 = 4*6 = 24 = 18h
003810E1 mov dword ptr [ebp-4],0FFFFFFFFh
003810E8 call operator new[] (0381506h)
003810ED add esp,4
003810F0 mov ebx,eax
//调用 operator new[](size_t size) 分配内存
003810DF push 18h //sizeof(testClass)*6 = 4*6 = 24 = 18h
003810E1 mov dword ptr [ebp-4],0FFFFFFFFh
003810E8 call operator new[] (0381506h)
003810ED add esp,4
003810F0 mov ebx,eax
delete[] ptc_a;
//调用 testClass::~testClass() (循环6次)
003810F2 test edi,edi
003810F4 je main+0A2h (0381122h)
003810F6 push offset testClass::~testClass (0381070h)
003810FB mov dword ptr [ebp-4],1
00381102 lea esi,[edi-4]
00381105 push dword ptr [esi] //压入数组个数 6
00381107 push 4
00381109 push edi
0038110A call `eh vector destructor iterator' (038141Fh)
//调用 operator delete[](void*,size_t) 释放内存
0038110F mov eax,dword ptr [esi]
00381111 lea eax,[eax*4+4]
00381118 push eax
00381119 push esi
0038111A call operator delete[] (0381411h)
0038111F add esp,8
::operator delete[](ptc1_a);
//调用 operator delete[](void*) 释放内存
00381122 push ebx
00381123 call operator delete[] (038140Ch)
00381128 add esp,4
ok,现在明白了吧。new delete 是编译器的关键字
new 先调用 ::operator new 分配内存,然后以分配的内存为 this调用构造函数
delete 先调用 析构函数,再调用 ::operator delete 释放内存
new X[size] 先调用 ::operator new[] 分配内存,在调用每个元素的构造函数
delete[] X 先调用 每个元素的析构函数,再调用 ::operator delete[] 释放内存
前面看过 ::operator new ::operator new[] 源码,其实都是调用 malloc 分配内存
::operator delete ::operator delete[] 都是调用 free 释放内存
//调用 testClass::~testClass() (循环6次)
003810F2 test edi,edi
003810F4 je main+0A2h (0381122h)
003810F6 push offset testClass::~testClass (0381070h)
003810FB mov dword ptr [ebp-4],1
00381102 lea esi,[edi-4]
00381105 push dword ptr [esi] //压入数组个数 6
00381107 push 4
00381109 push edi
0038110A call `eh vector destructor iterator' (038141Fh)
//调用 operator delete[](void*,size_t) 释放内存
0038110F mov eax,dword ptr [esi]
00381111 lea eax,[eax*4+4]
00381118 push eax
00381119 push esi
0038111A call operator delete[] (0381411h)
0038111F add esp,8
::operator delete[](ptc1_a);
//调用 operator delete[](void*) 释放内存
00381122 push ebx
00381123 call operator delete[] (038140Ch)
00381128 add esp,4
ok,现在明白了吧。new delete 是编译器的关键字
new 先调用 ::operator new 分配内存,然后以分配的内存为 this调用构造函数
delete 先调用 析构函数,再调用 ::operator delete 释放内存
new X[size] 先调用 ::operator new[] 分配内存,在调用每个元素的构造函数
delete[] X 先调用 每个元素的析构函数,再调用 ::operator delete[] 释放内存
前面看过 ::operator new ::operator new[] 源码,其实都是调用 malloc 分配内存
::operator delete ::operator delete[] 都是调用 free 释放内存
ok, 来看一下怎么来重载 这些操作符;
#include <stdio.h>
#include <stdlib.h>
#include <new.h>
#include <stdlib.h>
#include <new.h>
class testClass
{
public:
testClass(int iValue = 0)
{
m_iValue = iValue;
printf("testClass::testClass()\n");
}
{
public:
testClass(int iValue = 0)
{
m_iValue = iValue;
printf("testClass::testClass()\n");
}
~testClass()
{
printf("testClass::~testClass()\n");
}
{
printf("testClass::~testClass()\n");
}
void testFunc()
{
printf("testClass::testFunc() m_iValue = %d\n", m_iValue);
}
{
printf("testClass::testFunc() m_iValue = %d\n", m_iValue);
}
void* operator new(size_t Size)
{
printf("testClass::operator new(size_t)\n");
return malloc(Size);
}
{
printf("testClass::operator new(size_t)\n");
return malloc(Size);
}
void operator delete(void* pblock)
{
printf("testClass::operator delete(void*)\n");
if (nullptr != pblock)
free(pblock);
}
{
printf("testClass::operator delete(void*)\n");
if (nullptr != pblock)
free(pblock);
}
void* operator new[](size_t Size)
{
printf("testClass::operator new[](size_t)\n");
return malloc(Size);
}
{
printf("testClass::operator new[](size_t)\n");
return malloc(Size);
}
void operator delete[](void* pblock)
{
printf("testClass::operator delete[](void*)\n");
if (nullptr != pblock)
free(pblock);
}
private:
int m_iValue;
};
{
printf("testClass::operator delete[](void*)\n");
if (nullptr != pblock)
free(pblock);
}
private:
int m_iValue;
};
void main()
{
testClass* ptc = new testClass(1);
delete ptc;
testClass* ptc_a = new testClass[6];
delete[] ptc_a;
}
{
testClass* ptc = new testClass(1);
delete ptc;
testClass* ptc_a = new testClass[6];
delete[] ptc_a;
}
反汇编:
testClass* ptc = new testClass(1);
//调用重载 operator new(size_t) 分配内存
009010C5 push offset string "testClass::operator new(size_t)\n"... (090214Ch)
009010CA call printf (0901040h)
009010CF mov edi,dword ptr [__imp__malloc (0902054h)]
009010D5 push 4
009010D7 call edi
009010D9 mov esi,eax
//调用构造函数
009010DB add esp,8
009010DE mov dword ptr [ebp-10h],esi
009010E1 test esi,esi
009010E3 je main+73h (0901113h)
009010E5 push offset string "testClass::testClass()\n" (0902118h)
009010EA mov dword ptr [esi],1
009010F0 call printf (0901040h)
testClass* ptc = new testClass(1);
//调用重载 operator new(size_t) 分配内存
009010C5 push offset string "testClass::operator new(size_t)\n"... (090214Ch)
009010CA call printf (0901040h)
009010CF mov edi,dword ptr [__imp__malloc (0902054h)]
009010D5 push 4
009010D7 call edi
009010D9 mov esi,eax
//调用构造函数
009010DB add esp,8
009010DE mov dword ptr [ebp-10h],esi
009010E1 test esi,esi
009010E3 je main+73h (0901113h)
009010E5 push offset string "testClass::testClass()\n" (0902118h)
009010EA mov dword ptr [esi],1
009010F0 call printf (0901040h)
delete ptc;
//调用析构函数
009010F5 push offset string "testClass::~testClass()\n" (0902130h)
009010FA call printf (0901040h)
//调用重载 operator delete(void*) 释放内存
009010FF push offset string "testClass::operator delete(void*"... (0902170h)
00901104 call printf (0901040h)
00901109 push esi
0090110A call dword ptr [__imp__free (0902058h)]
00901110 add esp,10h
//调用析构函数
009010F5 push offset string "testClass::~testClass()\n" (0902130h)
009010FA call printf (0901040h)
//调用重载 operator delete(void*) 释放内存
009010FF push offset string "testClass::operator delete(void*"... (0902170h)
00901104 call printf (0901040h)
00901109 push esi
0090110A call dword ptr [__imp__free (0902058h)]
00901110 add esp,10h
testClass* ptc_a = new testClass[6];
//调用重载 operator new[](size_t)分配内存
00901113 push offset string "testClass::operator new[](size_t"... (0902194h)
00901118 call printf (0901040h)
0090111D push 1Ch
0090111F call edi
00901121 add esp,8
00901124 mov dword ptr [ptc],eax
00901127 mov dword ptr [ebp-4],0
0090112E test eax,eax
00901130 je main+0B1h (0901151h)
//调用每个元素的构造函数
00901132 push offset testClass::~testClass (0901070h)
00901137 push offset testClass::`default constructor closure' (09011B0h)
0090113C push 6
0090113E lea esi,[eax+4]
00901141 mov dword ptr [eax],6
00901147 push 4
00901149 push esi
0090114A call `eh vector constructor iterator' (0901530h)
0090114F jmp main+0B3h (0901153h)
00901151 xor esi,esi
00901153 mov dword ptr [ebp-4],0FFFFFFFFh
//调用重载 operator new[](size_t)分配内存
00901113 push offset string "testClass::operator new[](size_t"... (0902194h)
00901118 call printf (0901040h)
0090111D push 1Ch
0090111F call edi
00901121 add esp,8
00901124 mov dword ptr [ptc],eax
00901127 mov dword ptr [ebp-4],0
0090112E test eax,eax
00901130 je main+0B1h (0901151h)
//调用每个元素的构造函数
00901132 push offset testClass::~testClass (0901070h)
00901137 push offset testClass::`default constructor closure' (09011B0h)
0090113C push 6
0090113E lea esi,[eax+4]
00901141 mov dword ptr [eax],6
00901147 push 4
00901149 push esi
0090114A call `eh vector constructor iterator' (0901530h)
0090114F jmp main+0B3h (0901153h)
00901151 xor esi,esi
00901153 mov dword ptr [ebp-4],0FFFFFFFFh
delete[] ptc_a;
//调用每个元素的析构函数
0090115A test esi,esi
0090115C je main+0F2h (0901192h)
0090115E push offset testClass::~testClass (0901070h)
00901163 mov dword ptr [ebp-4],1
0090116A lea edi,[esi-4]
0090116D push dword ptr [edi]
0090116F push 4
00901171 push esi
00901172 call `eh vector destructor iterator' (0901449h)
//调用重载函数 operator delete[](void*) 释放内存
00901177 push offset string "testClass::operator delete[](voi"... (09021B8h)
0090117C call printf (0901040h)
00901181 add esp,4
00901184 test edi,edi
00901186 je main+0F2h (0901192h)
00901188 push edi
00901189 call dword ptr [__imp__free (0902058h)]
0090118F add esp,4
}
//调用每个元素的析构函数
0090115A test esi,esi
0090115C je main+0F2h (0901192h)
0090115E push offset testClass::~testClass (0901070h)
00901163 mov dword ptr [ebp-4],1
0090116A lea edi,[esi-4]
0090116D push dword ptr [edi]
0090116F push 4
00901171 push esi
00901172 call `eh vector destructor iterator' (0901449h)
//调用重载函数 operator delete[](void*) 释放内存
00901177 push offset string "testClass::operator delete[](voi"... (09021B8h)
0090117C call printf (0901040h)
00901181 add esp,4
00901184 test edi,edi
00901186 je main+0F2h (0901192h)
00901188 push edi
00901189 call dword ptr [__imp__free (0902058h)]
0090118F add esp,4
}
new new X[size] 后者需要为每个元素调用构造函数 ,后者还需要多分配4字节的内存保存数组大小
delete delete[] X 后者需要为每个元素调用析构函数,delete delete[] 绝对不是 调用虚构函数的
次数的差别,因为以new X[size] 分配的内存的前4个字节是保存数组的大小。所以
new 分配的用 delete 删除, new X[size] 用 delete[] X 删除, ok !
delete delete[] X 后者需要为每个元素调用析构函数,delete delete[] 绝对不是 调用虚构函数的
次数的差别,因为以new X[size] 分配的内存的前4个字节是保存数组的大小。所以
new 分配的用 delete 删除, new X[size] 用 delete[] X 删除, ok !
下面是 placement new delete 的实现,很简单.就不多说了.使用 placement new 需要<new.h>
#ifndef __PLACEMENT_NEW_INLINE
#define __PLACEMENT_NEW_INLINE
_Ret_notnull_
inline void* __CRTDECL operator new(size_t _Size, void* _Where) throw()
{
(void)_Size;
return _Where;
}
#ifndef __PLACEMENT_NEW_INLINE
#define __PLACEMENT_NEW_INLINE
_Ret_notnull_
inline void* __CRTDECL operator new(size_t _Size, void* _Where) throw()
{
(void)_Size;
return _Where;
}
inline void __CRTDECL operator delete(void*, void*) throw()
{
return;
}
{
return;
}
_Ret_notnull_
inline void* __CRTDECL operator new[](size_t _Size,void* _Where) throw()
{
(void)_Size;
return _Where;
}
inline void* __CRTDECL operator new[](size_t _Size,void* _Where) throw()
{
(void)_Size;
return _Where;
}
inline void __CRTDECL operator delete[](void*, void*) throw()
{
}
{
}
除了placement new delete new[] delete[]其他的 operator new delete new[] delete[]都可以重载
我还有一篇文章是讲解 placement new 的。
我还有一篇文章是讲解 placement new 的。
阅读全文
0 0
- new delete operator new oprator delete operator new[] operator delete[] 详解
- new/delete operator和operator new/delete
- new operator和delete operator
- operator new 和 operator delete
- operator new 和 operator delete
- operator new和operator delete
- operator new和operator delete
- Operator New/Delete
- operator new 和 delete
- operator new, new operator, delete new, new delete
- C++ 的 new 和 delete : new operator, operator new, placement new, delete operator, operator delete
- new/delete operator、operator new/delete、placement new
- 解析C++中的new、operator new、operator new[]和delete、operator delete、operator delete[](上)
- 解析C++中的new、operator new、operator new[]和delete、operator delete、operator delete[](下)
- 关于new/operator new和delete/operator delete的看法
- C++中的new/delete与operator new/operator delete
- C++中的new/delete与operator new/operator delete
- C++中的new/delete与operator new/operator delete
- Markdown语法,写的时候可以过来溜达溜达
- SpringBoot的数据缓存支持
- java字符串 删除指定字符的那些事
- Nginx+Tomcat搭建负载均衡
- 网站自动登录功能(安全-代码简洁)的设计
- new delete operator new oprator delete operator new[] operator delete[] 详解
- Web性能压力测试工具——Siege详解
- (一)如何制作信息管理系统的注册页面
- LintCode:M-带重复元素的排列
- CC26XX定时器以及按键中断
- python连接mysql ---处理数据
- 进入不了o的erp登陆界面(记录日常)
- python 数据表格的合并和重塑--pd.concat
- 使用CSDN-markdown编辑器