6.2.1 针对数组的new语意
Point类的定义,一个Point对象的大小是16个字节(3个float成员外加一个vptr):
class Point
{
public:
Point(float x = 0.0, float y = 0.0, float z = 0.0) : _x(x), _y(y), _z(z) { }
~Point(){};
virtual void somefuc() {};
private:
float _x, _y, _z;
};
main函数中动态申请含有10个Point对象的数组
int main(int argc, char* argv[])
{
Point *ppp = new Point[10];
delete []ppp;
}
看一下在VC6.0中针对数组的new语意是什么样的。main函数的汇编代码:
159: Point *ppp = new Point[10];
0040149D push 0A4h //operator new的参数,也就是需要为数组申请的内存大小,多申请了4个字节,用于存储cookie(元素个数)
004014A2 call operator new (00408930) // 调用operator new函数,调用结束后,EAX中存储了申请到的内存地址0x00941198
004014A7 add esp,4
004014AA mov dword ptr [ebp-18h],eax // 在栈上保存内存地址
004014AD mov dword ptr [ebp-4],0
004014B4 cmp dword ptr [ebp-18h],0 // 判断内存申请是否成功
004014B8 je main+78h (004014e8) // 申请内存失败跳过调用eh vector constructor iterator
004014BA push offset @ILT+0(Point::~Point) (00401005) // Point解构函数地址入栈
004014BF push offset @ILT+5(Point::`default constructor closure') (0040100a)// Point默认构造函数地址入栈
004014C4 mov eax,dword ptr [ebp-18h] // 申请到的内存地址存入EAX
004014C7 mov dword ptr [eax],0Ah // 将数组元素个数存入申请到的内存首地址中,也就是上面说的cookie
004014CD push 0Ah // 数组元素个数入栈
004014CF push 10h // Point对象的大小
004014D1 mov ecx,dword ptr [ebp-18h] // 申请到的内存地址放入ECX
004014D4 add ecx,4 // 内存地址加4,跳过了cookie,做为数组的地址
004014D7 push ecx // 数组地址入栈
004014D8 call `eh vector constructor iterator' (00408890) // 调用eh vector constructor iterator,在该函数会对数组元素逐一调用构造函数
004014DD mov edx,dword ptr [ebp-18h] // 内存地址放入EDX
004014E0 add edx,4 // EDX加4,成为数组地址
004014E3 mov dword ptr [ebp-24h],edx // 数组地址放入一个临时变量中
004014E6 jmp main+7Fh (004014ef)
004014E8 mov dword ptr [ebp-24h],0 // 申请内存失败时,临时变量设为0
004014EF mov eax,dword ptr [ebp-24h]
004014F2 mov dword ptr [ebp-14h],eax
004014F5 mov dword ptr [ebp-4],0FFFFFFFFh
004014FC mov ecx,dword ptr [ebp-14h]
004014FF mov dword ptr [ebp-10h],ecx // 将数组地址赋给ppp
160: delete []ppp;
00401502 mov edx,dword ptr [ebp-10h] //
00401505 mov dword ptr [ebp-20h],edx //
00401508 mov eax,dword ptr [ebp-20h] //
0040150B mov dword ptr [ebp-1Ch],eax // 倒腾来倒腾去的折腾啥?EDX、EAX、ebp-10h、ebp-20h、ebp-1Ch全都是数组地址
0040150E cmp dword ptr [ebp-1Ch],0 // 判断数组地址是否为空
00401512 je main+0B3h (00401523)
00401514 push 3
00401516 mov ecx,dword ptr [ebp-1Ch] // 数组地址放入ECX
00401519 call @ILT+15(Point::`vector deleting destructor') (00401014)// 在此函数中调用解构函数之后,调用delete释放内存,释放内存时会减4转为原始内存地址
0040151E mov dword ptr [ebp-28h],eax
00401521 jmp main+0BAh (0040152a)
00401523 mov dword ptr [ebp-28h],0