- 论坛徽章:
- 2
|
本帖最后由 cdsfiui 于 2016-09-28 11:55 编辑
对于对象数组而言,C++编译器会生成隐藏的代理函数,来用一个for循环初始化new出来的数组,用for循环来析构delete[]的对象。
这个在C++对象模型相关的书籍和文章里面都已经讲得比较清楚了。
但是我有个问题,我发现VC的debug版本,为单个delete对象,也生成一个scalar deleting destructor代理函数。
这个让我觉得不明白,因为我觉得没有这样的必要,单个对象的析构没有for循环,也没有析构到一半处理异常的问题。
为什么VC会这样? 我贴了一下代码在这里,很简单的:
- struct C{
- C(){
- cout << "ctor\n";
- }
- ~C(){
- cout << "dtor\n";
- }
- };
- int main(int argc, char *argv[])
- {
- C obj;//栈对象的析构没有涉及到scalar deleting destructor
- C*p = new C();
- delete p;//这里是我的问题所在,单个对象为什么需要scalar deleting destructor?
- return 0;
- }
复制代码 debug版下面生成的汇编代码如下,在main函数的尾部:
- delete p;
- 00E55D3F mov eax,dword ptr [p]
- 00E55D42 mov dword ptr [ebp-0F8h],eax
- 00E55D48 mov ecx,dword ptr [ebp-0F8h]
- 00E55D4E mov dword ptr [ebp-104h],ecx
- 00E55D54 cmp dword ptr [ebp-104h],0
- 00E55D5B je main+0D2h (0E55D72h)
- 00E55D5D push 1
- 00E55D5F mov ecx,dword ptr [ebp-104h]
- 00E55D65 call C::`scalar deleting destructor' (0E514E7h)
- 00E55D6A mov dword ptr [ebp-124h],eax
- 00E55D70 jmp main+0DCh (0E55D7Ch)
- 00E55D72 mov dword ptr [ebp-124h],0
- return 0;
- 00E55D7C mov dword ptr [ebp-0ECh],0
- 00E55D86 mov dword ptr [ebp-4],0FFFFFFFFh
- 00E55D8D lea ecx,[obj]
- 00E55D90 call C::~C (0E514DDh)
- 00E55D95 mov eax,dword ptr [ebp-0ECh]
- }
复制代码 看到C obj的析构是在地址00E55D90 call C::~C
而delete p的析构是在地址00E55D65 call C::`scalar deleting destructor' (0E514E7h)
我尝试编译这个程序的release版,未优化的版本,一样的结论。
问题
1. 为什么有这个区别? 如果堆上面的对象需要一个代理函数来调用析构+free,为什么构造的时候不需要一个代理函数来malloc+构造,而在析构的时候却需要。这个显得不对称。
2. 我用gcc也测试了一下这个程序,不加优化选项,也没有看到有个scalar deleting destructor之类的结构,加上调试信息,看反汇编也是直接callq xxxx <C::~C()>
还请板上朋友解释解释哈!
|
|