Which is better? Calling a Funtion by value, or calling by reference? | Sololearn: Learn to code for FREE!
New course! Every coder should learn Generative AI!
Try a free lesson
+ 10

Which is better? Calling a Funtion by value, or calling by reference?

30th Sep 2018, 7:16 AM
Mrityunjay Mani Tripathi
Mrityunjay Mani Tripathi - avatar
35 Answers
+ 7
Keep Learning. Keep Coding :)
1st Oct 2018, 2:34 AM
Infinity
Infinity - avatar
+ 6
Depends. If the value of the variable passed as argument has to be changed outside the function, use call be reference, otherwise use call by value. Interestingly, Call by reference can be used to return more than one values from a method!
30th Sep 2018, 7:30 PM
Infinity
Infinity - avatar
+ 6
Ketan Lalcheta Have a look at the disassembly the compiler produces. https://godbolt.org/z/YxXDvG Here's the function with pass by value being called: mov edx, DWORD PTR _y$[ebp] push edx mov eax, DWORD PTR _x$[ebp] push eax call int sum(int,int) ; sum and here is the function with the references being called: lea edx, DWORD PTR _z$[ebp] push edx lea eax, DWORD PTR _y$[ebp] push eax lea ecx, DWORD PTR _x$[ebp] push ecx call void sum2(int &,int &,int &) ; sum2 As you can see, each of the references have to be loaded and pushed onto the stack for the callee, just like the function that uses by value.
1st Oct 2018, 12:48 AM
aklex
aklex - avatar
+ 6
Ipang Addresses can be dynamic at runtime (thus making the reference arbritary at compile time). In this case what makes the addess dynamic is the fact that the variables are stored on the stack, and thus require using the current stack pointer to calculate its address at runtime. The second reason it’s arbritrary is because the function is not inlined (in this case due to optimizations being off). Even if the address is static, you still need to push the static address onto the stack for the callee, as any address could be passed to the single instance of that function. Your last paragraph is correct, except for the last part. Reference copies are always made, regardless of size if thats what you meant. I’m just making the point that the copy size will be the same if variable size is equal to size of a reference. If its greater than the size of the reference, you will have to copy more, which means more CPU instructions will be added. Thats where the advantage of reference comes in.
2nd Oct 2018, 5:32 PM
aklex
aklex - avatar
+ 5
Pass by reference is only better with non-primitive types. The perfomance won't be any different, and can become worse, if you pass primitive types by reference. Depends on the compiler, passing primitive types by value allows the compiler to do optimizations which is prevented by aliasing. It is cheap, more readable, and safer to develop when working with more people.
30th Sep 2018, 7:53 AM
Hoàng Nguyễn Văn
Hoàng Nguyễn Văn - avatar
+ 5
Ina TYVM for the information provided. I just edited my answer. Ketan Lalcheta since we were talking primitive types, passing a reference requires a pointer, which is 4 or 8 bytes, more than 1 byte of a char and just equal to 4 byte of an int. IMO, that won't be any better.
30th Sep 2018, 10:10 AM
Hoàng Nguyễn Văn
Hoàng Nguyễn Văn - avatar
+ 4
Nguyễn Văn Hoàng don't you think pass by reference saves object creation and memory utilisation ? reference passed ensures all operation are performed on same variable rather than creating new, performing operation and assigning back new to original one
30th Sep 2018, 8:22 AM
Ketan Lalcheta
Ketan Lalcheta - avatar
+ 4
It depends :-p Call by value when parameters are primitive types (or, possibly, very small objects or structs) and the value is read only within the function (or, modification not visible by the caller) Call by reference if the parameter is a larger object or structure, or if the value modification must be visible to the caller of the function If you want to pass a large object but show that it's content should not be modified by the function, consider using a const reference.
30th Sep 2018, 10:17 AM
ifl
ifl - avatar
+ 4
Ketan Lalcheta In your example it actually is taking up more memory on 64 bit systems, assuming int is 32 bit by default on your compiler. Before the function is called, the arguments are pushed onto the stack or stored in the cpu’s registers depending on the calling convention. You arent saving on any object creations either because the references have to also be created in order to be passed as parameters. Furthermore, since you are using a reference, it has to be derefernced each time the CPU reads or writes to it, which means you will have a higher latency whenever you access that variable compared to a local variable stored in a register.
30th Sep 2018, 2:51 PM
aklex
aklex - avatar
+ 4
aklex thanks for this...Mrityunjay Mani Tripathi appreciate your question as it taught me new thing today...Nguyễn Văn Hoàng too you to as you initiated answer which started changing my thoughts... thanks all
30th Sep 2018, 6:20 PM
Ketan Lalcheta
Ketan Lalcheta - avatar
+ 4
Ipang Its not that the original variable is being copied, it’s just that the address of the variable is being copied instead. You can see there’s a slight difference in the assembly, and thats what it is. (LOAD EFFECTIVE ADDRESS instead of MOVE). This is why for any variable less than or equal to the sizeof an of address on your system, you will not save on any copying. I hope that clears it up a little bit more, and if you have more questions feel free to ask.
2nd Oct 2018, 3:56 PM
aklex
aklex - avatar
+ 4
Ipang The address needs to be copied because the reference can hold the address of any arbitrary variable. The callee doesn’t know which variable it will be getting a reference to, so it needs this information from the caller. So to answer your question, the caller makes the copy. By sizeof I mean the sizeof the variable type, yes. So essentially if sizeof(int) <= sizeof(void*)
2nd Oct 2018, 4:35 PM
aklex
aklex - avatar
+ 3
Ketan Lalcheta when you pass arguments to void sum, an alias for each argument is created, and memory on stack space will be allocated to hold the alias, which is 4 bytes each on a 32-bit system. I assume you stated that the references to a and b won't occupy memory because sum is a function and not a class member. Can you explain more about that? This is a bit beyond my understanding, so I might as well be wrong.
30th Sep 2018, 2:50 PM
Hoàng Nguyễn Văn
Hoàng Nguyễn Văn - avatar
+ 3
Ketan Lalcheta What I mean is that the references themselves are variables aswell when they are used as parameters. When you pass a reference the caller creates an integer and copies the target variable’s address to it, then pushes it onto the stack for callee to use as a reference. In the end it’s practilly the same as copying the original integer and then pushing it onto the stack for the callee.
30th Sep 2018, 4:45 PM
aklex
aklex - avatar
+ 3
Thanks to everyone who participated in this thread. I never thought a single question can change the way I program. When I did the 'swapping values' program, the the values of the variable was swapped in call by reference, but not in call by value.
1st Oct 2018, 1:03 AM
Mrityunjay Mani Tripathi
Mrityunjay Mani Tripathi - avatar
+ 3
aklex It seems I had misunderstood copy variable with copy address, sorry. But then why do the addresses needed to be copied? can't the callee work with the original addresses instead of the copy? and where exactly the copy process takes place? in caller (caller makes copies) or callee scope (callee makes copies)? I didn't really understand the second paragraph, quoted "This is why for any variable less than or equal to the sizeof an of address on your system, you will not save on copying" do you mean the size of the variable type? like sizeof(int) or is it something else?
2nd Oct 2018, 4:25 PM
Ipang
+ 3
aklex First of all I want to thank you for being patient enough with my naive curiosity, but I can't help it, until I get a clear understanding of this matter, I won't stop wondering and asking why : ) I still need more information on the reason why copies are needed, as per your explanation the reference can hold an arbitrary address (random) but why is that? isn't it strictly holding the address of the variable it refers to? e.g. "&a" here it is a reference that holds the address of variable "a" right? not some arbitrary address (I'm confused). And also for the saving part, if I understood you correctly, in 64bit machines an address is 64bit (8 bytes) and it is 32bit (4 bytes) in 32bit machines (disregarding compiler defaults). So this means reference copies will be created anyway (by caller) if we pass any reference holding address of a variable whose type size is less than size of address, I hope I get it right this time ... Looking forward ...
2nd Oct 2018, 5:03 PM
Ipang
+ 3
Ketan Lalcheta Thank you, and that code would make an interesting test case, I'll be standing by, look forward to hearing more opinions from senior coders on this matter : )
3rd Oct 2018, 4:49 AM
Ipang
+ 2
Nguyễn Văn Hoàng please consider this as learning to enhance our knowledge... sole purpose is to gain knowledge... let's go by example : int sum (int a , int b) //call by value and return int variable void sum (int &a, int &b, int& c)// call by reference and c is the one which holds sum in this scenario, it's not taking more memory... it's just a function not class member... evenif first two argument are pointer, it's not getting occupied like class... only one pointer is required I.e. function pointer to map function with function call (in both cases of function call type, it is required) but for call as reference, you have saved two int object creation (evenif it's small).. still you feel one must not go with call by reference for primitive type...? cmiiw anywhere
30th Sep 2018, 11:12 AM
Ketan Lalcheta
Ketan Lalcheta - avatar
+ 2
Nguyễn Văn Hoàng yup , you were right... memory will be consumed while declaring variable before function call.. discard that part from last post
30th Sep 2018, 3:29 PM
Ketan Lalcheta
Ketan Lalcheta - avatar