#include <cstdio> class baseObj { public : int i; baseObj(int o) { i = o + 32; }; }; class childObj : public baseObj { public : childObj(int i):baseObj(i){} }; int main() { baseObj a = childObj(16); a.i += 64; printf("go %d",a.i); };i was expecting (in the time when i was writing this code) compiler to create two functions, that would carry out my constructors. even though this code is easy its interesting how different compilers deal with it. i've selected four compilers that is :
1. bcc32 (Borland C++ Compiler)
2. bcc55 (Borland C++ Compiler 5.5)
3. g++ (MinGW windows port)
4. g++ (under Red Hat linux)
As ive expected, both Borland compilers produces the same assembly code. resulting code even without turning on any optimization look like there are no objects used. and this is not what ive expected. compiler is smart enough and does not produce and additional functions. as we can see in line 4, compiler 'knows' that when object is already created it contains value 16+32=48 and produced assembler code looks like this :
push ebp mov ebp,esp add esp,-8 mov dword ptr [ebp-8],48 \ mov eax,dword ptr [ebp-8] |->baseObj a = childObj(16); mov dword ptr [ebp-4],eax / add dword ptr [ebp-4],64 -> a.i += 64; push dword ptr [ebp-4] \ push offset s@ |->a.i += 64; call @_printf / add esp,8 xor eax,eax pop ecx pop ecx pop ebp reteverything looks a bit different when we are using g++ compiler. in produced assembly code we can easily find constructor functions created by compiler. moreover examining code we will see that assembly version of our code behaves like i have predicted while writing it. assembly code shown below was generated with g++ compiler without any optimization.
main: pushl %ebp movl %esp, %ebp subl $8, %esp andl $-16, %esp movl $0, %eax subl %eax, %esp subl $8, %esp pushl $16 > push 16 on stack leal -8(%ebp), %eax > effective addr of 'a' object pushl %eax > push 'a' ptr on stack call _ZN8childObjC1Ei --> calling BaseObj constructor addl $16, %esp leal -8(%ebp), %eax movl (%eax), %eax movl %eax, -4(%ebp) leal -4(%ebp), %eax addl $64, (%eax) > do a.i += 64 subl $8, %esp pushl -4(%ebp) pushl $.LC0 call printf addl $16, %esp movl $0, %eax leave ret _ZN8childObjC1Ei: -> compiler created ChildObj constructor pushl %ebp movl %esp, %ebp subl $8, %esp subl $8, %esp pushl 12(%ebp) > push 16 on stack pushl 8(%ebp) > push 'a' ptr on stack call _ZN7baseObjC2Ei --> calling BaseObj constructor addl $16, %esp > delete locals leave ret _ZN7baseObjC2Ei: -> compiler created BaseObj constructor pushl %ebp movl %esp, %ebp movl 8(%ebp), %edx > store 'a' ptr in EAX register movl 12(%ebp), %eax > store 16 id EDX register addl $32, %eax > 16+32 movl %eax, (%edx) > store result in 'a' leave retthis code was created under Red Hat linux. the assembly file i got under cygwin is pretty the same except of same mingw specific lines.
a bit suprising (for me) was, that when i turned on optimization at level 1 code that i got looked like it was written without any objects. as we can see this code
main: pushl %ebp movl %esp, %ebp subl $8, %esp andl $-16, %esp subl $8, %esp pushl $112 -----------> 16+32+64 (none of the constructors need to be invoked) pushl $.LC0 call printf movl $0, %eax leave ret
as we see Borland compilers are trying to do some optimization even when user didnt asked for it, to get (almost) the same result using GNU compiler we need to turn the optimization on :)