Are Objects in PHP Assigned by Value or Reference

Are objects in PHP assigned by value or reference?

Why not run the function and find out?

$b = new Bar;
echo $b->getFoo(5)->value;
$b->test();
echo $b->getFoo(5)->value;

For me the above code (along with your code) produced this output:

Foo #5
My value has now changed

This isn't due to "passing by reference", however, it is due to "assignment by reference". In PHP 5 assignment by reference is the default behaviour with objects. If you want to assign by value instead, use the clone keyword.

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.'
?>

Are PHP5 objects passed by reference?

Objects are passed (and assigned) by reference. No need to use address of operator.

Granted what I typed is an oversimplification but will suit your purposes. The documentation states:

One of the key-points of PHP5 OOP that
is often mentioned is that "objects
are passed by references by default".
This is not completely true. This
section rectifies that general thought
using some examples.

A PHP reference is an alias, which
allows two different variables to
write to the same value. As of PHP5,
an object variable doesn't contain the
object itself as value anymore. It
only contains an object identifier
which allows object accessors to find
the actual object. When an object is
sent by argument, returned or assigned
to another variable, the different
variables are not aliases: they hold a
copy of the identifier, which points
to the same object.

For a more detailed explanation (explains the oversimplification as well as identifiers) check out this answer.

PHP Object Assignment vs Cloning

Objects are abstract data in memory. A variable always holds a reference to this data in memory. Imagine that $foo = new Bar creates an object instance of Bar somewhere in memory, assigns it some id #42, and $foo now holds this #42 as reference to this object. Assigning this reference to other variables by reference or normally works the same as with any other values. Many variables can hold a copy of this reference, but all point to the same object.

clone explicitly creates a copy of the object itself, not just of the reference that points to the object.

$foo = new Bar;   // $foo holds a reference to an instance of Bar
$bar = $foo; // $bar holds a copy of the reference to the instance of Bar
$baz =& $foo; // $baz references the same reference to the instance of Bar as $foo

Just don't confuse "reference" as in =& with "reference" as in object identifier.

$blarg = clone $foo;  // the instance of Bar that $foo referenced was copied
// into a new instance of Bar and $blarg now holds a reference
// to that new instance

Objects in foreach Loop are Passed by Reference Without &

PHP paradigm is that objects (and resources) are always references, while other types (base types or arrays) are copied, so the & operator has no effect on objects (and is meaningless on resources since only "special functions" i.e. external library modules can take them as parameters), but allows to pass variables of other types by reference.

Assigning Object as Value and Reference doesnt work Properly in PHP

Humm...PHP support both By Value and By Reference. However, there are a few quirks...


By default, PHP5 always assigns / passes objects by reference:

$obj1 = new stdClass();
$obj2 = $obj1;

print spl_object_hash($obj1);
print "<br>";
print spl_object_hash($obj2);

Output:

000000001ef37c150000000046e30ead
000000001ef37c150000000046e30ead

Basically, both $obj1 and $obj2 are pointers to the same object.


However, this is not true for primitive types (such as integer, string, etc...)

$var1 = "some string";
$var2 = $var1;
$var1 = "foo";

print $var1;
print '<br>';
print $var2;

Output:

foo
some string

Using & you can pass by reference primitives too.

$var1 = "some string";
$var2 = &$var1;
$var1 = "foo";

print $var1;
print '<br>';
print $var2;

Output:

foo
foo

And you can pass objects by value too

$obj1 = new stdClass();
$obj2 = clone $obj1;

print spl_object_hash($obj1);
print "<br>";
print spl_object_hash($obj2);

output:

0000000062516daa000000001745e928
0000000062516da9000000001745e928

In Short, by default primitive types are passed by value while objects are passed by reference.

PHP - why does passing by reference use the same amount of memory?

The answer is that objects cannot be passed by value. They are always passed by reference. The 'pass by reference' operator, '&', will do nothing other than wrap the object reference (i.e. a pointer) in a wrapper, then pass that new pointer.

As for the memory usage, there is no simple answer other than database query results seem to come with a lot of overhead, and you want to make your 'footprint' (i.e. any results returned from a database, or any variables) as small as possible.

Are multiple variable assignments done by value or reference?

With raw types this is a copy.

test.php

$a = $b = 0;

$b = 3;

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

Output:

int(0) 
int(3)

With objects though, that is another story (PHP 5)

test.php

class Obj
{
public $_name;
}

$a = $b = new Obj();

$b->_name = 'steve';

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

Output

object(Obj)#1 (1) { ["_name"]=> string(5) "steve" } 
object(Obj)#1 (1) { ["_name"]=> string(5) "steve" }

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.



Related Topics



Leave a reply



Submit