C++ compiler will synthesize the default copy constructor in the following situation. (From Inside C++ Object Model)
- When the class contains a member object of a class for which a copy constructor exists.
- When the class is derived from a base class for which a copy constructor exists.
- When the class declares one or more virtual functions
- When the class is derived from an inheritance chain in which one or more base classes are virtual.
We can see the class A is not in the 4 situations. So cl do NOT synthesize the default copy constructor for it. Maybe that's why 2 temp A objects constructed and destroyed.
From the disassemly window, We can see the following code, no A::A called. :
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)
But if we make the destructor virtual. We will get the following disassemble code, we can see the A::A is called. Then the result is as expected, only 1 A object created.
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)
cout << this
)? – Luisaluisevirtual
when it's necessary. On the other hand, if notvirtual
, thenprotected
is probably a good idea; and if you compile with-Wdelete-non-virtual-dtor
the compiler will flag all incorrect uses for you. – Leban