C++ 编译器会在以下情况下合成默认的复制构造函数。(来自 C++ 对象模型内部)
- 当类包含存在复制构造函数的类的成员对象时。
- 当类派生自存在复制构造函数的基类时。
- 当类声明一个或多个虚函数时
- 当类派生自一个或多个基类是虚拟的继承链时。
我们可以看到 A 类不在这 4 种情况下。所以 cl 不要为它合成默认的复制构造函数。也许这就是构造和销毁 2 个临时 A 对象的原因。
从 disassemly 窗口中,我们可以看到以下代码,没有调用 A::A。:
B b;
00B317F8 lea ecx,[b]
00B317FB call B::B (0B31650h)
00B31800 mov dword ptr [ebp-4],0
func(b);
00B31807 mov al,byte ptr [ebp-12h]
00B3180A mov byte ptr [ebp-13h],al
00B3180D mov byte ptr [ebp-4],1
00B31811 movzx ecx,byte ptr [ebp-13h]
00B31815 push ecx
00B31816 call func (0B31730h)
但是,如果我们将析构函数设为虚拟。我们会得到下面的反汇编代码,我们可以看到 A::A 被调用了。然后结果如预期的那样,只创建了 1 个对象。
B b;
00331898 lea ecx,[b]
0033189B call B::B (03316A0h)
003318A0 mov dword ptr [ebp-4],0
func(b);
003318A7 push ecx
003318A8 mov ecx,esp
003318AA mov dword ptr [ebp-1Ch],esp
003318AD lea eax,[b]
003318B0 push eax
003318B1 call A::A (0331900h)
003318B6 mov dword ptr [ebp-20h],eax
003318B9 call func (03317D0h)