Are Arrays in PHP Copied as Value or as Reference to New Variables, and When Passed to Functions

Are arrays in PHP copied as value or as reference to new variables, and when passed to functions?

For the second part of your question, see the array page of the manual, which states (quoting) :

Array assignment always involves value
copying. Use the reference operator to
copy an array by reference.

And the given example :

<?php
$arr1 = array(2, 3);
$arr2 = $arr1;
$arr2[] = 4; // $arr2 is changed,
// $arr1 is still array(2, 3)

$arr3 = &$arr1;
$arr3[] = 4; // now $arr1 and $arr3 are the same
?>



For the first part, the best way to be sure is to try ;-)

Consider this example of code :

function my_func($a) {
$a[] = 30;
}

$arr = array(10, 20);
my_func($arr);
var_dump($arr);

It'll give this output :

array
0 => int 10
1 => int 20

Which indicates the function has not modified the "outside" array that was passed as a parameter : it's passed as a copy, and not a reference.

If you want it passed by reference, you'll have to modify the function, this way :

function my_func(& $a) {
$a[] = 30;
}

And the output will become :

array
0 => int 10
1 => int 20
2 => int 30

As, this time, the array has been passed "by reference".



Don't hesitate to read the References Explained section of the manual : it should answer some of your questions ;-)

Are PHP Variables passed by value or by reference?

It's by value according to the PHP Documentation.

By default, function arguments are passed by value (so that if the value of the argument within the function is changed, it does not get changed outside of the function). To allow a function to modify its arguments, they must be passed by reference.

To have an argument to a function always passed by reference, prepend an ampersand (&) to the argument name in the function definition.

<?php
function add_some_extra(&$string)
{
$string .= 'and something extra.';
}

$str = 'This is a string, ';
add_some_extra($str);
echo $str; // outputs 'This is a string, and something extra.'
?>

Why can't I append an element in a PHP class' nested array?

You try to access element 0 in an associative array you cannot do that.

public function App($elm) {
$V = $this->cms[0]['V']; // here

PHP how come one element of the array is by reference and the other by value when passing a two element array as a by value parameter?

A little complex formulated answer I found at https://www.php.net/manual/en/language.references.whatdo.php

I will translate the answer to this particular situation.

The thing many people may not realise, is, is that $a =& $b does not mean that $a references now to $b, but $a and $b BOTH become references to the same value that was originally contained in $b.

So when evaluating $ref = &$arr[0] ; the $arr[0] element and the $ref become both references to the 3 value.

Now when an array is passed as a parameter by value, the array is always duplicated. Same happens here.

Which means the $arr[0] reference is duplicated too, i.e. in the duplicate array another reference is created to the same 3 value. So we have $ref, the original $arr[0] and the $arr[0] within the function all being references to the 3 value.

When either of these three references gets an assignment, of course the value changes.

Thank you @Sammitch for setting me on the right track!!!

Why does Copy On Write not work on PHP Array which has reference element?

$b = &$a;

This is pass by reference and in other words, a new shallow copy of $a. So, any modification in $b will reflect in $a and vice-versa.

Demo: https://3v4l.org/r86j4

$c = $b;

This is pass by value. So, any modification in $c will only reflect in $c.

$a = [1, &$x];

This is the same as the first example. The second location in the array is now a new copy of same $x.

$x = 1;

$a = [1, &$x];

$b = $a;

$c = $b;

$c[1] = 2;

$b = $a and $c = $b above is pass by value. So, this assignment clones a new copy of $a, however, the &$x in the 2nd location is preserved.

That being said, it's never a good practice to assign variables as pass by reference to arrays individual locations(except for educational purposes). You would soon land into debugging issues and code's undefined behaviors.

All in all, if you want to create a new shallow copy, use &, else use a simple assignment for deep copy(More info).

Update:

the 2nd location is preserved because the second element is a reference, so it holds the reference and naturally the modification reflects everywhere. In the below example, it is pass by value.

<?php

$x = 4;

$y = &$x;

$a = [1,2,$y];

$b = $a;
$b[2] = 40;

var_dump($a);
var_dump($b);

Demo: https://3v4l.org/W9PIR

When is it good to use pass by reference in PHP?

The following does not apply to objects, as it has been already stated here. Passing arrays and scalar values by reference will only save you memory if you plan on modifying the passed value, because PHP uses a copy-on-change (aka copy-on-write) policy. For example:

# $array will not be copied, because it is not modified.
function foo($array) {
echo $array[0];
}

# $array will be copied, because it is modified.
function bar($array) {
$array[0] += 1;
echo $array[0] + $array[1];
}

# This is how bar shoudl've been implemented in the first place.
function baz($array) {
$temp = $array[0] + 1;
echo $temp + $array[1];
}


# This would also work (passing the array by reference), but has a serious
#side-effect which you may not want, but $array is not copied here.
function foobar(&$array) {
$array[0] += 1;
echo $array[0] + $array[1];
}

To summarize:

  • If you are working on a very large array and plan on modifying it inside a function, you actually should use a reference to prevent it from getting copied, which can seriously decrease performance or even exhaust your memory limit.

  • If it is avoidable though (that is small arrays or scalar values), I'd always use functional-style approach with no side-effects, because as soon as you pass something by reference, you can never be sure what passed variable may hold after the function call, which sometimes can lead to nasty and hard-to-find bugs.

  • IMHO scalar values should never be passed by reference, because the performance impact can not be that big as to justify the loss of transparency in your code.

PHP 5 | Objects Passed by Reference / Value vs Copy on Write | When added as class property

As the manual page you link to says, the statement "objects are passed by reference" is not a good description of what is happening. A better way to think of it is that the "value" of an object is a handle, pointer, or address to something that exists in a different space.

Whether you assign it to an object property, an array element, or a normal variable, this "value" remains the same, and changes to the object are visible wherever you look at them. Copying the value uses a few bytes (the size of the pointer) but doesn't duplicate the memory of the object itself.

As a final clarification, the "write" in "copy-on-write" refers to modification of an existing value, after copying it from one place to another. So writing $foo = $bar, where $bar is an array, will not duplicate the memory used by the array, but subsequently writing $foo[0]=1; or $bar[0]=1 will, because the two copies need to be distinguished. This doesn't actually come into play in your example; if it did, it would be just the "object pointer" that was copied, so very little extra memory would be needed.

PHP: Passing array by reference fail

Because $v never modified. Inside the function you assign the variable into another variable. So nothing ever happen to the old $vett

try something like:

function foo(&$vett) {
$vett[] = "ciao";
echo __LINE__;
var_dump($vett);
}

$v = array();
foo($v);
var_dump($v);


Related Topics



Leave a reply



Submit