The Internals of Passing Variables by Reference and Value

The concept of passing variables by reference or value isn't new to seasoned PHP developers; but often, newer developers aren't as familiar with this concept. Simply put: "by reference" means that you are passing the pointer (memory address) of a variable, while "by value" means you are copying the contents of a variable.

Tobby Hagler, Director of Engineering
#Development | Posted

The concept of passing variables by reference or value isn't new to seasoned PHP developers; but often, newer developers aren't as familiar with this concept. Simply put: "by reference" means that you are passing the pointer (memory address) of a variable, while "by value" means you are copying the contents of a variable.

Variables, Pointers, and Scope

Internally, variables are simply memory addresses that point to some location in RAM that holds the value that your code assigns to it. Unlike some "stricter" languages, PHP doesn't preallocate the space in RAM for the size of the expected value; this is why you can easily change data types (i.e. from an integer to a string). Variables don't actually hold the contents you assign; instead, they hold references to the memory address that does hold that value. When you declare $a = 1;, you have allocated a new chunk of memory and assigned an integer value of 1 to that location in memory.

Variable scope is the property of a programming language that dictates the context in which a variable is defined. In PHP, scope is almost always limited to a single context, such as a function or a loop block. Normally, because of variable scope, any changes made to a variable within a function (or other code block) are limited to only that instance. Even if the same variable name is used in another function, one function can't normally affect another function's variables.

There are some exceptions to this. Notably, declaring a variable with the global operator will place the variable in the 'global' scope. Some variables are called Super Globals, and exist in all scopes, such as $_GET, $_POST, and the obvious $GLOBALS.

By Value

What happens internally is that a function or assignment operator creates a new variable, complete with its own memory address. It then copies the value of the original variable into the space in memory. When you write $b = $a; you have allocated a new memory pointer, and copied the content found in $a's memory location to the new memory location referenced by $b.

When you pass a variable by value (the default behavior) to a function, you are creating a copy of your original variable's value for use within that function. The advantage to this is that variable scope is limited to that function, so it can be useful when you need to make temporary changes to calculate a larger result. The disadvantage is that this uses more memory, and you must return the updated value of your variable.

By Reference

What happens internally is that the function accepts the memory address of the variable, and references the contents of the original variable directly.

Most PHP developers first see examples of passing variables by reference in function definitions, such as:

1
2
3
function my_func (&arg1, $arg2 = NULL) {
  //...
}

The ampersand (&) denotes that the variable should be passed by reference.

The most obvious result is that any change to $arg1 within the scope of that function is felt by the code calling that function. In fact, you are changing the content of the original variable by accessing it via your new pointer. The advantage of this is there is less memory overhead, and there's no need to return the value of the original variable. The disadvantage is that your original variable is directly affected.

Passing "advanced" data types, such as objects, are handled by passing it by reference. This is because of the limited amount of memory within the registers of the CPU, so passing a variable by value is hardware-bound.

TL;DNR

Passing a variable "by value" creates a copy of the original variable. This increases memory usage by the size of that variable's original content.

Passing a variable "by reference" creates a new pointer that points to the same address in memory; effectively allowing other functions to change the original variable. This only increases memory usage by the size of a few bytes (the size of the memory address).

Passing an object (such as stdClass) is always passed by reference.

Tobby Hagler

Tobby Hagler

Director of Engineering