Copy constructor ignored when passing by value to a function with unspecified number of arguments.
-
Does anybody know why a class copy constructor gets ignored by compiler when objects of the class get passed to a function with unspecified number of arguments ? The following code illustrates this. When the test runs, the output is 2 1 2 3 4, whereas I would expect 2 0 0 0 0. Please ignore the awfulness of the implementation of the MyClass::Foo function – it is just to prove that the compiler has passed the objects by value using the default copy constructor where as the class contains user-defined copy constructor. Thanks, Serge #include "stdafx.h" class MyClass { public: MyClass(int first, int second) : a(first), b(second) {} MyClass(const MyClass& r) : a(0), b(0) {} void Foo(int arg, ...) { int* pArg = &arg; printf("%i %i %i %i %i\n", arg, *(pArg + 1), *(pArg + 2), *(pArg + 3), *(pArg + 4)); } private: int a, b; }; void main() { MyClass mc1(1, 2); MyClass mc2(3, 4); mc1.Foo(2, mc1, mc2); }
-
Does anybody know why a class copy constructor gets ignored by compiler when objects of the class get passed to a function with unspecified number of arguments ? The following code illustrates this. When the test runs, the output is 2 1 2 3 4, whereas I would expect 2 0 0 0 0. Please ignore the awfulness of the implementation of the MyClass::Foo function – it is just to prove that the compiler has passed the objects by value using the default copy constructor where as the class contains user-defined copy constructor. Thanks, Serge #include "stdafx.h" class MyClass { public: MyClass(int first, int second) : a(first), b(second) {} MyClass(const MyClass& r) : a(0), b(0) {} void Foo(int arg, ...) { int* pArg = &arg; printf("%i %i %i %i %i\n", arg, *(pArg + 1), *(pArg + 2), *(pArg + 3), *(pArg + 4)); } private: int a, b; }; void main() { MyClass mc1(1, 2); MyClass mc2(3, 4); mc1.Foo(2, mc1, mc2); }
According to the standard (§ 5.2.2 Function call), arguments passed in the
...
part of the argument list must be either primitive (arithmetic types, pointers) or POD-structs. A POD-struct is a class that behaves as a simple aggregate of data, with no user-defined constructors (you can think of POD-structs as classes where it is permissible to do bitwise copy between objects). So you're entering the realm of undefined behavior in your program. Joaquín M López Muñoz Telefónica, Investigación y Desarrollo -
Does anybody know why a class copy constructor gets ignored by compiler when objects of the class get passed to a function with unspecified number of arguments ? The following code illustrates this. When the test runs, the output is 2 1 2 3 4, whereas I would expect 2 0 0 0 0. Please ignore the awfulness of the implementation of the MyClass::Foo function – it is just to prove that the compiler has passed the objects by value using the default copy constructor where as the class contains user-defined copy constructor. Thanks, Serge #include "stdafx.h" class MyClass { public: MyClass(int first, int second) : a(first), b(second) {} MyClass(const MyClass& r) : a(0), b(0) {} void Foo(int arg, ...) { int* pArg = &arg; printf("%i %i %i %i %i\n", arg, *(pArg + 1), *(pArg + 2), *(pArg + 3), *(pArg + 4)); } private: int a, b; }; void main() { MyClass mc1(1, 2); MyClass mc2(3, 4); mc1.Foo(2, mc1, mc2); }
Your copy constructor is not being called. The reason for this can be found in the partial disassembly of the line mc1.Foo(2, mc1, mc2);
31: mc1.Foo(2, mc1, mc2);
00401090 mov eax,dword ptr [ebp-0Ch] ---->points to mc2.b and loads it to eax
00401093 push eax ----->push value to stack for function
00401094 mov ecx,dword ptr [ebp-10h] ---->points to mc2.a and loads it to eax
00401097 push ecx ----->push value to stack for function
00401098 mov edx,dword ptr [ebp-4] ---->points to mc1.b and loads it to eax
0040109B push edx ----->push value to stack for function
0040109C mov eax,dword ptr [ebp-8] ---->points to mc1.a and loads it to eax
0040109F push eax ----->push value to stack for function
004010A0 push 2 ----->This is the first arg
004010A2 lea ecx,[ebp-8]
004010A5 push ecx
004010A6 call @ILT+0(MyClass::Foo) (00401005)
004010AB add esp,18hThis seems to be compiler optimization if I am not mistaken. However if you write MyClass mc2(mc1); then the value of mc2 members a & b are 0 i.e. your copy constructor is called. Atul Sonork 100.13714 netdiva
-
Does anybody know why a class copy constructor gets ignored by compiler when objects of the class get passed to a function with unspecified number of arguments ? The following code illustrates this. When the test runs, the output is 2 1 2 3 4, whereas I would expect 2 0 0 0 0. Please ignore the awfulness of the implementation of the MyClass::Foo function – it is just to prove that the compiler has passed the objects by value using the default copy constructor where as the class contains user-defined copy constructor. Thanks, Serge #include "stdafx.h" class MyClass { public: MyClass(int first, int second) : a(first), b(second) {} MyClass(const MyClass& r) : a(0), b(0) {} void Foo(int arg, ...) { int* pArg = &arg; printf("%i %i %i %i %i\n", arg, *(pArg + 1), *(pArg + 2), *(pArg + 3), *(pArg + 4)); } private: int a, b; }; void main() { MyClass mc1(1, 2); MyClass mc2(3, 4); mc1.Foo(2, mc1, mc2); }
Thanks for the answers, now it’s clear. As the disassembly shows, the compiler generated ‘default copy constructor’ and ignored the user-defined copy constructor. Surely, in this situation, the compiler must warn about what it is doing? Interesting, what the standard says about user defined copy constructors. Does it mention that copy constructors are not applicable in some cases? And how many case are there ?