Tutorial :Is there any temporary created while returning an object from function?



Question:

when ever a function has a object passed by value it uses either copy constructor or bit wise copy to create a temporary to place on stack to use inside the function,How about some object returned from function ?

//just a sample code to support the qn  rnObj somefunction()  {  return rnObj();  }  

and also explain how the return value is taken to the called function.


Solution:1

As can be judged by the other answers - the compiler can optimize this.

A concrete example generated using MSVC, to explain how this is possible (as asked in one of the comments) -

Take a class -

class AClass  {  public:     AClass( int Data1, int Data2, int Data3 );       int GetData1();    private:     int Data1;     int Data2;     int Data3;  };  

With the following trivial implementation -

AClass::AClass( int Data1, int Data2, int Data3 )  {      this->Data1 = Data1;      this->Data2 = Data2;      this->Data3 = Data3;  }    int AClass::GetData1()  {      return Data1;  }  

And the following calling code -

AClass Func( int Data1, int Data2, int Data3 )  {      return AClass( Data1, Data2, Data3 );  }    int main()  {      AClass TheClass = Func( 10, 20, 30 );      printf( "%d", TheClass.GetData1() );  }  

(the printf() added just to make sure the compiler doesn't optimize everything away...).
In a non-optimized code, we would expect Func() to create a local AClass on its stack, construct it there and copy it as its return variable.

However, the generated assembly actually looks like (removing unneeded lines) -

_TEXT SEGMENT  ___$ReturnUdt$ = 8   ; size = 4  _Data1$ = 12         ; size = 4  _Data2$ = 16         ; size = 4  _Data3$ = 20         ; size = 4    mov     eax, DWORD PTR _Data3$[esp-4]  mov     ecx, DWORD PTR _Data2$[esp-4]  mov     edx, DWORD PTR _Data1$[esp-4]  push    esi  mov     esi, DWORD PTR ___$ReturnUdt$[esp]  push    eax  push    ecx  push    edx  mov     ecx, esi  call    ??0AClass@@QAE@HHH@Z    ; AClass::AClass  mov     eax, esi  pop     esi  ret     0  

The 3 function variables are extracted from the stack and placed into eax, ecx and edx.
Another forth value is placed into esi (and passed on to ecx).
The constructor is called with the 3 parameters on the stack, and ecx still containing the forth value.

Let's take a look in the constructor -

_TEXT SEGMENT  _Data1$ = 8    ; size = 4  _Data2$ = 12   ; size = 4  _Data3$ = 16   ; size = 4    mov    edx, DWORD PTR _Data2$[esp-4]  mov    eax, ecx  mov    ecx, DWORD PTR _Data1$[esp-4]  mov    DWORD PTR [eax], ecx  mov    ecx, DWORD PTR _Data3$[esp-4]  mov    DWORD PTR [eax+4], edx  mov    DWORD PTR [eax+8], ecx    ret    12   ; 0000000cH  

The 3 constructor parameters are read into offsets of eax - eax being a copy of ecx, the forth parameter from the call above.
So, the constructor builts the object where it is told to - the forth parameter of Func().

And, you guessed it, the forth parameter of Func() is actually the real single place in the entire program where a constructed AClass exists. Let's look at the relevant part of main() -

_TEXT SEGMENT  _TheClass$ = -12    ; size = 12  _main PROC    sub    esp, 12    push   30  push   20  lea    eax, DWORD PTR _TheClass$[esp+20]  push   10  push   eax  call   ?Func@@YA?AVAClass@@HHH@Z    ; Func  

12 bytes are reserved for an AClass and the three arguments to Func() are passed, along with the forth one - pointing to those 12 bytes.

This is a specific example with a specific compiler. Other compilers do this differently. But that's the spirit of things.


Solution:2

The C++ Standard states that the compiler can choose to create a temporary object, using the copy constructor, or it can choose to optimise away the temporary.

There is a wikipedia article on the subject, with numerous references here.


Solution:3

Most modern compilers will be able to avoid the temporary object creation if the optimization is turned on. See Named Return Value Optimization for more details.


Solution:4

The compiler is allowed to perform a copy on return. Most compilers won't. You must, however, make sure that rnObj has an accessible copy constructor.


Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »