By-Reference vs. By-Copy

December 4th, 2008 | by sean |

For those of you who do not know what by-reference and by-copy refer to, the refer to the way an argument is passed between functions. When an argument is passed by copy, it creates a new copy of the variable in memory.  When an argument is passed by reference, only the pointer to the variable is copied to the next function.  The main reason for this is that with pass-by-reference, you can modify a variable in subsequent functions and the changes will be present in the calling function.  For more info on pointers, watch this video.

In most low-level languages, you can easily determine whether or not an argument to a function is passed by reference or by copy.  But in high-level, script-like languages such as ColdFusion, there isn’t an easy way to keep track of this.

The main rule of thumb in coldfusion is that all complex objects except arrays are passed by reference.  This is easy enough until you start dealing with complex structs.  When you append one struct to another, something similar happens (sort of).  Simple variables like strings and numbers won’t be changed when they are changed in the new struct, but complex objects will (even arrays).

Ok, to illustrate this a little better take a look at the following code:

<cfset struct1 = StructNew() />
<cfset struct1.myKey = “abc” />
<cfset struct1.myArray = ArrayNew(1)>
<cfset myFunc(struct1, 4) />
<cfdump var=”#struct1#”><cfabort>

<cffunction name=”myFunc” returntype=”void”>
<cfargument name=”newStruct” />
<cfargument name=”index” />

<cfset var l = StructNew() />
<cfset structAppend(L,arguments.newStruct) />
<cfif index GT 0>
<cfset ArrayAppend(l.myArray, index)/>
<cfset l.myKey = l.myKey & index />
<cfoutput><p>#l.myKey# for index #arguments.index#</p></cfoutput>
<cfset myFunc(arguments.newStruct, arguments.index - 1) />
</cfif>
</cffunction>

I start with struct1 outside the function and add to key/value pairs.  One is a simple string and the other is a blank array.  When I pass it into the function, I have the function immediately append (not copy) it to a local struct.  I then modify the array and string by appending the current index to both.

Once the function call is done, and has looped a few times, I output the original struct.  The array has been modified but the string has not.  Something similar would occur if I were to add in new key/value pairs in the function. The new key/value pairs will appear in the original struct.

This can pose a huge problem for code if you have a series of cascading functions that pass a single struct through all of them, inspite of appending the struct to a local struct variable, you will still be modifying the struct in all of the originating functions.

Tags: , , , , , ,

Post a Comment