As in my previous post, I'm using Visual Studio 2010 Express in Debug mode and WinDbg to view the disassembly.
First a short catch up what I've done in Part 1. We have added two integers in a function called add.
int main()
{
int a = 3;
int b = 7;
int c = add(a, b);
return 0;
}
When using the pass-by-value version of add, copies of 3 and 7 were pushed on the stack.
When using the pass-by-const-reference, the memory addresses were pushed on the stack.
This was clearly shown in the memory view of WinDbg.
I'm now going to evolve the add example above a little bit.
Let's say we have user-defined class according to below.
class MyClass { public: int a_, b_; };
Further, let's modify the main function.
int main() { MyClass myClass = {3, 7}; int c = add(myClass); return 0; }
I'm using the same idea as in Part 1. But my add function takes a MyClass type instead of two integers.
First up is the pass-by-value example. Below is the C++ code and the disassembly with the stack.
int add(MyClass myClass)
{
return myClass.a_+myClass.b_;
}
WinDbg - disassembly of main (about to execute the call instruction) and its stack |
First is 7 (myClass.b_) pushed on the stack, and then is 3 (myClass.a_) pushed on the stack.
The blue and purple frames is the result of the copying, i.e. the push instructions.
Now let's continue with the disassembly of the add function.
WinDbg - disassembly of add function (about to execute the move eax instruction) and its stack |
Finally, it is time to investigate what is going on the the pass-by-const-reference case for our user-defined class.
int add(const MyClass &myClass) { return myClass.a_+myClass.b_; }
WinDbg - Disassembly of main function (about to execute the call instruction) and its stack |
The lea instruction stores the memory address of the first member in myClass, i.e 3 (myClass.a_) in eax, which is then pushed on the stack (blue frame).
Then we are ready to execute the add function, i.e. the call instruction.
WinDbg - Disassembly of add function (about to execute the move eax instruction) and its stack |
Same procedure is done for myClass.b_. The move ecx dword ptr [ebp+8] instruction, sets ecx to the address of myClass.a_. Next instruction add eax (3) to the contents of the address which ecx+4 points to, i.e value 7.
We have finally investigate what is happening for both integers and user-defined classes when using pass-by-value and pass-by-const-reference. When the user-defined classes grows in terms of members, the copying can be very expensive.
You are welcome to leave comments, complaints or questions!