为何C++编译器要为有虚函数的类生成给new[]/delete[]用的vector ctor/dtor?解决办法

为何C++编译器要为有虚函数的类生成给new[]/delete[]用的vector ctor/dtor?
最近在研究new/delete对象数组的时候,编译器生成的代码,发现很奇怪的地方:

例如,我有下面这一小段代码:
C/C++ code

struct O{
    int o;
    ~O(){}
};
struct A {
    int a;
    virtual ~A(){}
};
struct B:virtual A{
    int b;
    virtual ~B(){}
};
void main(void){
    O* po= new O[3];
    delete[] po;
    A* pa= new A[3];
    delete[] pa;
    B* pb= new B[3];
    delete[] pb;
}


我在VC下面用/d1ReportAllClassLayout会在output窗口里面得到各个类的对象模型:

1>class O size(4):
1> +---
1> 0 | o
1> +---
1>class A size(8):
1> +---
1> 0 | {vfptr}
1> 4 | a
1> +---
1>A::$vftable@:
1> | &A_meta
1> | 0
1> 0 | &A::{dtor}
1>A::{dtor} this adjustor: 0
1>A::__delDtor this adjustor: 0
1>A::__vecDelDtor this adjustor: 0

1>class B size(12):
1> +---
1> 0 | {vbptr}
1> +---
1> +--- (virtual base A)
1> 4 | {vfptr}
1> 8 | a
1> +---
1>B::$vbtable@:
1> 0 | 0
1> 1 | 4 (Bd(B+0)A)
1>B::$vftable@:
1> | -4
1> 0 | &B::{dtor}
1>B::{dtor} this adjustor: 4
1>B::__delDtor this adjustor: 4
1>B::__vecDelDtor this adjustor: 4
1>vbi: class offset o.vbptr o.vbte fVtorDisp
1> A 4 0 4 0
--------------------
问题:
(1) 为什么要为A和B生成vector ctor和dtor:
1>A::{dtor} this adjustor: 0
1>A::__delDtor this adjustor: 0
1>A::__vecDelDtor this adjustor: 0

1>B::{dtor} this adjustor: 4
1>B::__delDtor this adjustor: 4
1>B::__vecDelDtor this adjustor: 4

既然析构函数已经是虚函数了,对象实例的虚表指针就能指向正确的虚表位置,调用正确的dtor来做析构。
为什么要生成DelDtor这样的函数呢? 用ecx计数器来循环调用ctor和dtor不行么? 非要弄个函数出来?

(2) 我跟踪了一下反汇编的代码:
O*po=new O[3]没有调用vector ctor.
delete[] po调用了vector dtor.

A*pa=new A[3]先做了件奇怪的事情:
push offset A::~A()
push offset A::A()
(2.1)上面这两个push到底在干什么?

然后调用了vector ctor: call 'eh vector constructor iterator'
(2.2)ecx计数循环调用ctor不就行了,干嘛弄个vector ctor iterator出来?

(2.3)为什么A类型有调用vector ctor,而O类型没有?
delete[] pa的时候调用了vector dtor.

(3)B* pb=new B[3];
push offset B::'vbase desstructor' // (3.1)这里更奇怪了,push基类的dtor,岂不是要故意造成内存泄漏,因为delete调用的是基类的dtor啊
push offset B::B
...
call 'eh vector base constructor iterator' // (3.2)怎么还是调用基类的ctor? 没有看件另一行call指令来调用B类的ctor啊。难道B类自身不构造了?

delete []pb;
我发现汇编的实现是Push 3以后干了一堆事情然后call operator delete[]
(3.3)这里怎么没有调用vector dtor? 而O和A类型都调用了?

------解决方案--------------------
O* pa= new A[3];
delete[] pa;
这种代码是错误的。

只能
A* pa= new A[3];
delete[] pa;
所以编译器为这种情况生成一个特定的 虚构函数没啥奇怪的。
------解决方案--------------------
探讨

O* pa= new A[3];
delete[] pa;
这种代码是错误的。

只能
A* pa= new A[3];
delete[] pa;
所以编译器为这种情况生成一个特定的 虚构函数没啥奇怪的。

------解决方案--------------------
探讨

O* pa= new A[3];
delete[] pa;
这种代码是错误的。

只能
A* pa= new A[3];
delete[] pa;
所以编译器为这种情况生成一个特定的 虚构函数没啥奇怪的。

------解决方案--------------------
探讨

引用:

O* pa= new A[3];
delete[] pa;
这种代码是错误的。

只能
A* pa= new A[3];
delete[] pa;
所以编译器为这种情况生成一个特定的 虚构函数没啥奇怪的。

主楼程序那里写 O* pa= new A[3]; 了?不是本来写的就是 A* pa= new A[3]; 吗?