这段代码比以前的代码复杂一些,同样分段来查看。先看004023C0—00402400这段函数调用前处理堆栈的这里略过;看0040240B这句,重点要搞清楚dword ptr [ebp+8]里是什么,回顾一下刚才入栈的顺序析构函数、构造函数、数组元素的个数、元素的长度、数组的起始地址、EBP(栈基址寄存器);按照栈先进后出的原则,那dword ptr [ebp+8]就是数组的起始地址(其他参数也按照这个方法计算出来)。再看这个调用dword ptr [ebp+14h],按照刚才的算法地址存放着数的构造函数地址,那么这里与为单个类对象申请内存时构造是一样的。00402411—00402417这3句也很清楚,将数组的起始地址移动了一个元素的长度。0040241A这句调转到004023FA,而004023FA—00402406这几句计算当前元素构造的个数,从0开始计数,看到构造组数是从第一个开始一直到最后一个元素。这里分析出当为一个类new数组时,它实际上多了4个字节(用来存放数组元素的个数)。那么如果new不是一个类数组,一个基本数据类型或者是一个结构体的数组呢?如果 new是一个基本数据类型(long 、int等)的数组,上面的那种情况是不会出现的(不会多出4个字节来存放无素的个数),而对结构体则分两种情况,如果结构体中不包函数成员那么和基本数据类型一样,具体过程大家可以自己测试分析,这里不再赘述。
4 delete[]与delete的差别
上一节对new操作做了详细的讨论,这一节来讨论一下delete[]与delete的差别;试验时用的类还是上面的CMemoryItem类。
4.1释放类对象数组时的跟踪
delete[]与delete的差别主要在于前者用来释放new的数组,者用来释放new的单个对象,先把CMemoryItem类的析构函数的virtual修饰符去掉,然后看看两段代码片段的执行情况。
代码1:
CMemoryItem* pItem = new CMemoryItem[10];
delete[] pItem;
执行输出:
Construct CMemoryItem Nember[1]
Construct CMemoryItem Nember[2]
Construct CMemoryItem Nember[3]
Construct CMemoryItem Nember[4]
Construct CMemoryItem Nember[5]
Construct CMemoryItem Nember[6]
Construct CMemoryItem Nember[7]
Construct CMemoryItem Nember[8]
Construct CMemoryItem Nember[9]
Construct CMemoryItem Nember[10]
Destructor CMemoryItem Nember[10]
Destructor CMemoryItem Nember[9]
Destructor CMemoryItem Nember[8]
Destructor CMemoryItem Nember[7]
Destructor CMemoryItem Nember[6]
Destructor CMemoryItem Nember[5]
Destructor CMemoryItem Nember[4]
Destructor CMemoryItem Nember[3]
Destructor CMemoryItem Nember[2]
Destructor CMemoryItem Nember[1]
|