给出程序:
Visual Studio给出的输出是:132242。
前两个13和最后两个42.是对应的,分别是main函数中的局部变量b的构造和析构。问题出在中间的两个2,说明在调用函数func的时候创建了两个临时的A。
看到这个程序,第一眼的感觉应该是:因为func是参数是值传递,所以b传给func时,调用了A的拷贝构造函数,从b生成了一个A的临时变量,推出func时,这个临时变量析构,所以应该只有一个2.
但是为什么会有两次呢?打开disassembly window,我们可以看到如下的汇编代码:
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的析构函数改成virtual,这样,输出的结果就是13242,中间只有1个2,说明只有一个临时的A被创建了出来,是我们期望的结果。汇编代码如下:
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)
回想Inside C++ object model中说到的只有在4中情况下编译器才会给我们生成缺省拷贝构造函数:
- 类包含的成员变量是object,并且这个object的类有拷贝构造函数。
- 类继承自一个基类,这个基类有拷贝构造函数。
- 类声明了1个或者多个虚函数。
- 类继承自一个基类,这个基类有1个或者多个虚函数。
所以在原来的代码中A不属于上面4类,所以编译器不会为它生成一个缺省拷贝构造函数。