语言参考
在线手册:中文 英文
PHP手册

引用的解释

Table of Contents


语言参考
在线手册:中文 英文
PHP手册
PHP手册 - N: 引用的解释

用户评论:

sneskid at hotmail dot com (16-Mar-2012 06:19)

There is no built in method (yet) to check if two variables are references to the same piece of data, but you can do a "reference sniff" test. This is rarely needed, but can be very useful. The function bellow is a slightly modified version of this technique I saw in a forum regarding this comparison limitation.

<?php
function is_ref_to(&$a, &$b)
{
   
$t = $a;
    if(
$r=($b===($a=1))){ $r = ($b===($a=0)); }
   
$a = $t;
    return
$r;
}

$varA = 1;
$varB = $varA;
$varC =&$varA;

var_dump( is_ref_to($varA, $varB) ); // bool(false)
var_dump( is_ref_to($varA, $varC) ); // bool(true)
?>

The test above uses a two step process to be 100% generic.
But if you are sure the variables being tested will not be a certain value, example null, then use that value to allow a one step check.

<?php
function is_ref_to_1step(&$a, &$b)
{
   
$t = $a;
   
$r=($b===($a=null));
   
$a = $t;
    return
$r;
}
?>

LDRut (13-Mar-2012 03:11)

@krauth, you somewhat mistate what is going on.

In the PHP 5.3 version, each element of $objs is assigned a reference to the value of $a. The do, and should, always have the exact same value. Every time the value of $a is overwritten, each and every element of $objs assumes the new value.

In the PHP 4 version you are assigning a reference to a reference. This is unrolled so that $a is removed from the chain - that is the value of $objs[] is not a reference to $a which is a reference to the new expression, it is instead a direct reference to the value of the new expression at the time of the assignment.

In PHP 5.3 ALL objects are passed by reference so neither ampersand has any legitimate need any longer. The correct edit is to remove BOTH ampersands.

<?php
echo "new correct PHP 5 style, ** removal of & in 'new' assignment and array assignment**:\n";
$objs = array();
foreach (array(
37, "Wisconsin", 3.14159) as $i) {
   
$a = new Gotcha($i);
   
$objs[] = $a;
}
?>

This is the exact semantic equivalent to your old 4.3 code.

Anonymous (24-Feb-2012 05:21)

$counter = 0;

while (odbc_fetch_row($rs))
  {
  $compname=odbc_result($rs,"CheckNum");
  $conname=odbc_result($rs,"DteIssued");
  echo "<tr><td>$compname</td>";
  echo "<td>$conname</td></tr>";

   $counter++;
   if($counter>50){ break; }

  }
odbc_close($conn);

echo "</table>";

misterherr at freenet dot de (07-Feb-2012 01:00)

@ krauth dot spam1 at gmail dot com:

You are confusing yourself and others. The problem is the intermediate variable $a, if you unset it in the foreach loop you will get even different results.

krauth dot spam1 at gmail dot com (12-Jan-2012 09:19)

Here's a simple demonstration that "$var =& new ..." and "$var = new ..." are NOT equivalent, as suggested in several places.  We came across this when trying to fix the PHP 5.3 deprecation notice "Assigning the return value of new by reference is deprecated".  Simply removing the ampersand actually broke the code, and in fact it seems that the statment with the ampersand is the one that does not create a reference.  Very confusing.

<?php
class Gotcha {
    var
$x;
    public function
Gotcha($init_value) {
       
$this->x = $init_value;
    }
}

echo
"<PRE>\n\n";

echo
"old PHP 4 style, generates 'deprecated' warnings:\n";
$objs = array();
foreach (array(
37, "Wisconsin", 3.14159) as $i) {
   
$a =& new Gotcha($i);
   
$objs[] =& $a;
}
var_export($objs);
echo
"\n\n";

echo
"new PHP 5 style, ** only change is removal of & in 'new' assignment **:\n";
$objs = array();
foreach (array(
37, "Wisconsin", 3.14159) as $i) {
   
$a = new Gotcha($i);
   
$objs[] =& $a;
}
var_export($objs);
echo
"\n\n";

echo
"php version = " . phpversion() . "\n";
?>

Output is:

old PHP 4 style, generates 'deprecated' warnings:
array (
  0 =>
  Gotcha::__set_state(array(
     'x' => 37,
  )),
  1 =>
  Gotcha::__set_state(array(
     'x' => 'Wisconsin',
  )),
  2 =>
  Gotcha::__set_state(array(
     'x' => 3.14159,
  )),
)

new PHP 5 style, ** only change is removal of & in 'new' assignment **:
array (
  0 =>
  Gotcha::__set_state(array(
     'x' => 3.14159,
  )),
  1 =>
  Gotcha::__set_state(array(
     'x' => 3.14159,
  )),
  2 =>
  Gotcha::__set_state(array(
     'x' => 3.14159,
  )),
)

php version = 5.3.3-7+squeeze3

bjb6371 at rit dot edu (15-Mar-2011 02:48)

I've personally found the clone operation to be less than desirable in creating duplicate objects. I've therefore resided to the solution of using a Copyable interface which requires a single method, copy, to be implemented. Copy would then perform the assignment to a new instance of the object from the $this reference. This prevents referencing issues between cloned copies of the same object.

If anyone has a more robust solution to a string reference acting "static" across cloned objects please let me know. I've given up at this point.

caslav dot sabani at gmail dot com (13-Dec-2010 03:48)

Consider this when using references:

<?php

class Test
{
    public
$var;
}

$a = new Test();
$a->var = 10;

$b = $a;

$c =& $a;

echo
'<b>$a</b>:';
echo
'<pre>';
print_r( $a );
echo
'</pre>';

unset(
$b );

echo
'after <b>unsetting</b> $b  <b>$a</b> is:';
echo
'<pre>';
print_r( $a );
echo
'</pre>';

unset(
$c );

echo
'after <b>unsetting</b> $c <b>$a</b> is:';
echo
'<pre>';
print_r( $a );
echo
'</pre>';

$a = new Test();
$a->var = 10;

$b = $a;

$c =& $a;

echo
'<b>$a</b>:';
echo
'<pre>';
print_r( $a );
echo
'</pre>';

$b = NULL;

echo
'after <b>nulling</b> $b  <b>$a</b> is:';
echo
'<pre>';
print_r( $a );
echo
'</pre>';

$c = NULL;

echo
'after <b>nulling</b> $c <b>$a</b> is:';
echo
'<pre>';
print_r( $a );
echo
'</pre>';

?>

This outputs:

$a:

Test Object
(
    [var] => 10
)

after unsetting $b $a is:

Test Object
(
    [var] => 10
)

after unsetting $c $a is:

Test Object
(
    [var] => 10
)

$a:

Test Object
(
    [var] => 10
)

after nulling $b $a is:

Test Object
(
    [var] => 10
)

after nulling $c $a is:

zoranbankovic at gmail dot com (16-Oct-2010 09:59)

If someone wants to add slashes to multidimensional array directly, can use recursive (pass-by-reference) function like this:
<?php
function slashit(&$aray, $db_link)
{
  foreach (
$aray as $key => &$value)
   if(
is_array($value)) slashit($value, $link);
   else
$aray[$key] = mysql_real_escape_string($value, $db_link);
}

// Test:
$fruits = array (
   
"fruits"  => array("a" => "or'ange", "b" => "ban'ana", "c" => "apple'"),
   
"numbers" => array(1, 2, 3, 4, 5, 6),
   
"holes"   => array("fir'st", 5 => "sec'ond", "thir'd"),
   
"odma"    => "jugo'slavija"
);

// You have to make link to the database or can use addslashes instead of mysql_real_escape_string and remove $link from function definition

slashit($fruits, $dbLink);
echo
"<pre>"; print_r($fruits); echo "</pre>";
?>

// Output:
Array
(
    [fruits] => Array
        (
            [a] => or\'ange
            [b] => ban\'ana
            [c] => apple\'
        )

    [numbers] => Array
        (
            [0] => 1
            [1] => 2
            [2] => 3
            [3] => 4
            [4] => 5
            [5] => 6
        )

    [holes] => Array
        (
            [0] => fir\'st
            [5] => sec\'ond
            [6] => thir\'d
        )

    [odma] => jugo\'slavija
)

dev dot php at linke-t dot net (30-Aug-2010 10:01)

I thought Yeah pointer likly behavior... but i watched serilized objects and what i did see? referenced Objects are outputed like the object self.

Here is a simple code, it shows that the references are sweet but in some case (storing objects to $_SESSION or Database) unuseable:

<?php
class foo{
    private static
$id_c = 0;
    public
$ref;
    public
$id;
    public function
foo(){
       
$this->id=self::$id_c++;
    }   
}
$a = new foo();
$b = new foo();
$a->ref = &$b;

print_r($a);
echo
"<br/>";
print_r($b);
echo
"<br/><br/>";

$a->ref->id++;
echo
"increment \$a->ref->id++;<br/><br/>";

print_r($a);
echo
"<br/>";
print_r($b);
echo
"<br/><br/>";
echo
"\$a2=unserialize(serialize(\$a));<br/><br/>";
$a2=unserialize(serialize($a));

print_r($a2);
echo
"<br/>";
print_r($b);
echo
"<br/><br/>";

$a2->ref->id++;
echo
"increment \$a2->ref->id++;<br/><br/>";

print_r($a2);
echo
"<br/>";
print_r($b);
echo
"<br/>";
?>

Output on PHP 5.3.3:
foo Object ( [ref] => foo Object ( [ref] => [id] => 1 ) [id] => 0 )
foo Object ( [ref] => [id] => 1 )

increment $a->ref->id++;

foo Object ( [ref] => foo Object ( [ref] => [id] => 2 ) [id] => 0 )
foo Object ( [ref] => [id] => 2 )

$a2=unserialize(serialize($a));

foo Object ( [ref] => foo Object ( [ref] => [id] => 2 ) [id] => 0 )
foo Object ( [ref] => [id] => 2 )

increment $a2->ref->id++;

foo Object ( [ref] => foo Object ( [ref] => [id] => 3 ) [id] => 0 )
foo Object ( [ref] => [id] => 2 )

after unserialize $a2->ref isn't any more a reference.

To save items for the next request, you must avoid references and save all objects of a class in an array. To get a PHP-reference you could write a function like:
<?php
function get_obj_by_ref($ref){
    global
$_array_where_objects_of_class_foo_are_stored;
   
$r = &$_array_where_objects_of_class_foo_are_stored[$ref];
    return
$r;
}
?>

I am unhappy about this behavior of PHP. I does not watch like a feature ... ;)

gnuffo1 at gmail dot com (28-Aug-2010 03:07)

If you want to know the reference count of a particular variable, then here's a function that makes use of debug_zval_dump() to do so:

<?php
function refcount($var)
{
   
ob_start();
   
debug_zval_dump($var);
   
$dump = ob_get_clean();

   
$matches = array();
   
preg_match('/refcount\(([0-9]+)/', $dump, $matches);

   
$count = $matches[1];

   
//3 references are added, including when calling debug_zval_dump()
   
return $count - 3;
}
?>

debug_zval_dump() is a confusing function, as explained in its documentation, as among other things, it adds a reference count when being called as there is a reference within the function. refcount() takes account of these extra references by subtracting them for the return value.

It's also even more confusing when dealing with variables that have been assigned by reference (=&), either on the right or left side of the assignment, so for that reason, the above function doesn't really work for those sorts of variables. I'd use it more on object instances.

However, even taking into account that passing a variable to a function adds one to the reference count; which should mean that calling refcount() adds one, and then calling debug_zval_dump() adds another, refcount() seems to have aquired another reference from somewhere; hence subtracting 3 instead of 2 in the return line. Not quite sure where that comes from.

I've only tested this on 5.3; due to the nature of debug_zval_dump(), the results may be completely different on other versions.

Youssef Omar (15-Dec-2009 08:27)

This is to show the affect of changing property of object A through another object B when you pass object A as a property of another object B.

<?php
 
// data class to be passed to another class as an object
 
class A{
     public
$info;
    function
__construct(){
       
$this->info = "eeee";
    }
 }
 
 
// B class to change the info in A obj
 
class B_class{
     public
$A_obj;
   
    function
__construct($A_obj){
       
$this->A_obj $A_obj;
    }
    public function
change($newVal){
       
$this->A_obj->info = $newVal;
    }
 }

 
// create data object from the A
 
$A_obj = new A();
 
// print the info property
 
echo 'A_obj info: ' . $A_obj->info . '<br/>';
 
 
// create the B object and pass the A_obj we created above
 
$B_obj = new B_class($A_obj);
 
// print the info property through the B object to make sure it has the same value 'eeee'
 
echo 'B_obj info: ' . $B_obj->A_obj->info . '<br/>';
 
 
// chage the info property
 
$B_obj->change('xxxxx');
 
// print the info property through the B object to make sure it changed the value to 'xxxxxx'
 
echo 'B_obj info after change: ' . $B_obj->A_obj->info . '<br/>';
 
// print the info property from the A_obj to see if the change through B_obj has affected it
 
echo 'A_obj info: ' . $A_obj->info . '<br/>';

?>

The result:

A_obj info: eeee
B_obj info: eeee
B_obj info after change: xxxxx
A_obj info: xxxxx

strata_ranger at hotmail dot com (30-Sep-2009 07:59)

Note that in PHP5 you generally don't need the reference operator -- at all -- when dealing with class objects, because PHP5 implements objects using Instances (which are more like C pointers than PHP's references system).

For example:
<?php
//
// Since PHP 5
//

$foo = new stdClass();

// $bar and $foo are still holding the same (single) object
$bar = $foo;
var_dump($foo, $bar)
// object(stdClass)#1 (0) { }
// object(stdClass)#1 (0) { }

$bar->member = "Something";
var_dump($foo, $bar);
// object(stdClass)#1 (1) {
//  ["member"]=>
//  string(9) "Something"
// }
// object(stdClass)#1 (1) {
//   ["member"]=>
//   string(9) "Something"
// }

// Use the 'clone' keyword to make a separate copy of the object
$bar = clone $foo;
$bar->member = "Something";
var_dump($foo, $bar);
// object(stdClass)#1 (0) { }
// object(stdClass)#2 (1) {
//   ["member"]=>
//   string(9) "Something"
// }

?>

Anonymous (01-Sep-2009 09:07)

After hours of confusion and reading tons of posts I finally figured out that replacing PHP 4 style object creation, where new is assigned by reference:

$node_obj =& new someClass($somearg, $moreargs);

which in PHP 5.3.0 generates an E_STRICT message telling you that "Assigning the return value of new by reference is deprecated"

with the following, where & has been removed:

$node_obj = new someClass($somearg, $moreargs);

in some cases (at least in recursive loops while creating a tree of nodes containing child nodes) requires

unset($node_obj);

before the actual object assignment line to avoid all child nodes becoming identical.

Hope that delicate piece of information will save someone else a few hours.

wernerdegroot at nospam dot gmail (14-Jul-2009 07:56)

In the following case you don't have to use = & operator when returning a reference:

<?php

   
class a {
        public
$a = 1;
    }
   
    class
b {
        static
$var;
       
        public static function &
gvar($i) {
            if(!(isset(
b::$var[$i]))) {
               
b::$var[$i] = new a;
            }
           
            return
b::$var[$i];
        }
    }
   
   
$b = new b;
   
$a = b::gvar(1);
   
$a->a = 14;
   
   
$c = b::gvar(1);
    echo
$c->a; // 14
?>

Note the $a = b::gvar(1) instead of $a = & b::gvar(1)!!!

midir (28-Feb-2009 07:44)

Here is a good magazine article (PDF format) that explains the internals of PHP's reference mechanism in detail: http://derickrethans.nl/files/phparch-php-variables-article.pdf

It should explain some of the odd behavior PHP sometimes seems to exhibit, as well as why you can't create "references to references" (unlike in C++), and why you should never attempt to use references to speed up passing of large strings or arrays (it will make no difference, or it will slow things down).

It was written for PHP 4 but it still applies. The only difference is in how PHP 5 handles objects: passing object variables by value only copies an internal pointer to the object. Objects in PHP 5 are only ever duplicated if you explicitly use the clone keyword.

bytepirate (09-Feb-2009 10:00)

in additon to blakes comment. try this:

<?php
$strlen
=60000;
$bstring=str_repeat("X",$strlen);
$astring=$bstring;
$starttime=microtime(true);
for(
$i=0;$i<=$strlen;$i++){
  if(
$i==strlen($astring))
     echo
"End of String<br>";
}
echo (
microtime(true)-$starttime)." seconds expired";
?>

and now change '$astring=$bstring;' to '$astring=&$bstring;'
on my system its 200 times slower with the reference.
increase $strlen and it gets even worse ;-)

(PHP 5.25 on UNIX)

ivan at mailinator dot com (09-Dec-2008 01:09)

A little gotcha (be careful with references!):

<?php
$arr
= array('a'=>'first', 'b'=>'second', 'c'=>'third');
foreach (
$arr as &$a); // do nothing. maybe?
foreach ($arr as $a);  // do nothing. maybe?
print_r($arr);
?>
Output:

Array
(
    [a] => first
    [b] => second
    [c] => second
)

Add 'unset($a)' between the foreachs to obtain the 'correct' output:

Array
(
    [a] => first
    [b] => second
    [c] => third
)

blake (15-Aug-2008 03:22)

To ffmandu13 at hotmail dot com, that's not correct. If you do a little research, you'll see that the Zend Engine employs "copy-on-write" logic, meaning that variables will be referenced instead of copied until it's actually written to. There's really no need to circumvent Zend's internal optimizations, since they're probably much more advanced than you think. Here's a good link to read over:

http://bytes.com/forum/thread769586.html

As stated, there's rarely (if ever) a need to use references for optimization purposes. When in doubt, remember that in most cases, the Zend Engine > you.

ffmandu13 at hotmail dot com (26-Jul-2008 03:06)

Just a side note to make developpers more careful about references.
References are pretty much useful when you try to optimize your code.

By the way, the time gained by referenced variables will depend of the variable type.

Integer and Float variables will work quite as fast referenced or not.
Whereas String and Array should be always passed by reference (you mostly divide by 10 the execution time).
Objects are automatically referenced by PHP.

Enjoy the references !

zzo38 (16-Jul-2008 09:08)

You can make references like pointers. Example:
<?php
  $a
=6;
 
$b=array(&$a); // $b is a pointer to $a
 
$c=array(&$b); // $c is a pointer to $b
 
$d=7;
 
$c[0][0]=9; // $a is 9
 
$c[0]=array(&$d); // $b is a pointer to $d
 
$c[0][0]=4; // $d is 4
 
$b=array(&$a); // $b is a pointer to $a again
 
echo $a.$b[0].$c[0][0].$d; // outputs 9994
?>
These kind of pointers may even be passed to functions or returned from functions, copied and stored in multiple arrays/variables/objects, etc.

jasonpvp at gmail dot com (11-Jul-2008 12:16)

To change values in a multi-dimensional array while looping through:

$var=array('a'=>array(1,2,3),'b'=>array(4,5,6));

foreach ($var as &$sub) {
  foreach ($sub as &$element) {
    $element=$element+1;
  }
}

var_dump($var);

------------------------------
produces:
------------------------------
array(2) {
  ["a"]=>
  array(3) {
    [0]=>
    int(2)
    [1]=>
    int(3)
    [2]=>
    int(4)
  }
  ["b"]=>
  array(3) {
    [0]=>
    int(5)
    [1]=>
    int(6)
    [2]=>
    int(7)
  }
}

mpapec (27-Jun-2008 01:23)

It's strange that function definition AND call to the same function must have "&" before them.

$arr = array();
$ref =& oras($arr['blah'], array());
$ref []= "via ref";
print_r($arr);

/* result
Array
(
    [blah] => Array
        (
            [0] => via ref
        )

)
*/

// perl like ||=
function &oras (&$v, $new) {
  $v or $v = $new;
  return $v;
}

dnhuff at acm dot org (09-Jun-2008 08:40)

This is discussed before (below) but bears repeating:

$a = null; ($a =& null; does not parse) is NOT the same as unset($a);

$a = null; replaces the value at the destination of $a with the null value;

If you chose to use a convention like $NULL = NULL;

THEN, you could say $a =& $NULL to break any previous reference assignment to $a (setting it of course to $NULL), which could still get you into trouble if you forgot and then said $a = '5'. Now $NULL would be '5'.

Moral: use unset when it is called for.

Dave at SymmetricDesigns dot com (21-May-2008 07:24)

Another example of something to watch out for when using references with arrays.  It seems that even an usused reference to an array cell modifies the *source* of the reference.  Strange behavior for an assignment statement (is this why I've seen it written as an =& operator?  - although this doesn't happen with regular variables).
<?php
    $array1
= array(1,2);
   
$x = &$array1[1];   // Unused reference
   
$array2 = $array1// reference now also applies to $array2 !
   
$array2[1]=22;      // (changing [0] will not affect $array1)
   
print_r($array1);
?>
Produces:
    Array
    (
    [0] => 1
    [1] => 22    // var_dump() will show the & here
    )

I fixed my bug by rewriting the code without references, but it can also be fixed with the unset() function:
<?php
    $array1
= array(1,2);
   
$x = &$array1[1];
   
$array2 = $array1;
    unset(
$x); // Array copy is now unaffected by above reference
   
$array2[1]=22;
   
print_r($array1);
?>
Produces:
    Array
    (
    [0] => 1
    [1] => 2
    )

Radek at cz (25-Apr-2008 07:35)

It took me a long while until I fully understood the sentence mentioned above:

"They (references) are not like C pointers; instead, they are symbol table aliases."

Here is a little example to that.

<?php
class AnyClass {
    public
$member;
    public function
__construct($val) {
       
$this->member = $val;
    }
}

$manyObjects = array();
$obj = null;

for(
$i = 0; $i < 5;$i++) {
   
$obj = new AnyClass($i); // create new instance
   
$manyObjects[] = &$obj; // i did not wanted to copy, just store the reference in the array, which turned out to be WRONG (it is not reference to the CLASS INSTANCE what is stored in the array, but rather reference to what variable with NAME $obj CURRENTLY holds).
// so we end up as shown below
}

for(
$i = 0; $i < 5;$i++) {
    echo
"Value:".$manyObjects[$i]->member."\r\n";
}   

/**
 * Output is :
 * Value:4
 * Value:4
 * Value:4
 * Value:4
 * Value:4

 * instead of expected

 * Value:0
 * Value:1
 * Value:2
 * Value:3
 * Value:4
 */

// If we change the value of $obj later in the script, all members would be changed in that moment

$obj = 1;
print_r($manyObjects);
/*
Array
(
    [0] => 1
    [1] => 1
    [2] => 1
    [3] => 1
    [4] => 1
)
*/
?>

Hope this spares someone few hours of time ;-)

Anonymous (22-Apr-2008 07:42)

To henrik at newdawn dot dk, 28-Oct-2007

No, it's not strange.
$this->$var['key'] tries to look up 'key' in the array $var and then use that for the property name. $this->{$var}['key'], on the other hand...

alexey at gmail dot com (25-Nov-2007 08:47)

I will describe how references interact with global variables.

Consider the following example. You create a DOM tree and then you use two functions. The first chooses an arbitrary tree element, while the second uses that element. Let us use a global variable as the means of communication between the two functions:

// global variable
var $dom_el;

test1(); // call first function
test2(); // call second function

function test1() {
global $dom_el, $Doc;

$dom_el = &$Doc->childNodes->item(0);
}

function test2() {
global $dom_el;

// $dom_el does not contain the reference! You cannot use it here.
// I am using PHP 4.4.6
}

If we assign a reference to the desired tree node in the first function then surprisingly the reference will disappear after the first function returns. That is, that reference is not saved in the global variable. Most likely, it is a feature of PHP 4 language. Specifically, I am using PHP 4.4.6. Thus, using a global variable to pass a reference from one function to another does not work.

However, if we save the reference as a field of an object, then the reference is preserved. Therefore, we need to wrap the global variable
in a class:

class Pointer {
var $i;

function Pointer() {
$this->i=null;
}

function set(&$_i) {
$this->i = &$_i;
}

function &get() {
return $this->i;
}
}

?>

Now the code looks like this:

$dom_el=new Pointer();

function test1() {
global $dom_el, $Doc;
$tmp = &$Doc->childNodes->item(0);
$dom_cur->set($tmp);
}

function test2() {
global $dom_el;

$tmp = &$dom_cur->get();
//$tmp has the desired reference
}

marco at greenlightsolutions dot nl (15-Nov-2007 10:38)

I ran into a bit of a problem recently, with an array copy resulting in a reference copy of one of the elements instead of a clone. Sample code:

<?php
$a
=array(1 => "A");
$b=&$a[1];
$c=$a; // should be a deep cloning
$c[1]="C";
var_dump($a[1]); // yields 'C' instead of 'A'
?>

After some searching, I found that it was a known bug which would be too costly to fix (see http://bugs.php.net/bug.php?id=20993). There was supposed to be some documentation on this behaviour on this page:

"Due to peculiarities of the internal workings of PHP, if a reference  is made to a single element of an array and then the array is copied, whether by assignment or when passed by value in a function call, the reference is copied as part of the array.  This means that changes to any such elements in either array will be duplicated in the other array (and in the other references), even if the arrays have different scopes (e.g. one is an argument inside a function and the other is global)!  Elements that did not have references at the time of the copy, as well as references assigned to those other elements after the copy of the array, will behave normally (i.e. independent of the other array)."

However, this paragraph appears to have been removed from this page at some point, presumably because it was a bit obscure. The comments section seem to be a proper place for this, though.

warnickr at gmail dot com (10-Nov-2007 09:15)

I must say that it has been rather confusing following all of the explanations of PHP references, especially since I've worked a lot with C pointers.  As far as I can tell PHP references are the same as C pointers for all practical purposes.  I think a lot of the confusion comes from examples like the one shown below where people expect that a C pointer version of this would change what $bar references. 

<?php
function foo(&$var)
{
   
$var =& $GLOBALS["baz"];
}
foo($bar);
?>

This is not the case.  In fact, a C pointer version of this example (shown below) would behave exactly the same way (it would not modify what bar references) as the PHP reference version.

int baz = 5;
int* bar;
void foo(int* var)
{
    var = &baz;
}
foo(bar);

In this case, just as in the case of PHP references, the call foo(bar) doesn't change what bar references.  If you wanted to change what bar references, then you would need to work with a double pointer like so:

int baz = 5;
int* bar;
void foo(int** var)
{
    *var = &baz;
}
foo(&bar);

henrik at newdawn dot dk (27-Oct-2007 11:21)

A note for those of you that are using constructs like the following:
return $this->$MyVarName
in your objects.

Consider the following:
class Test {
        var $MyArray = array();
        function add($var) {
                $this->$var[rand(1,100)] = rand(1,100);
        }
        function show($var) {
                echo "\nEcho from Test:\n";
                print_r($this->$var);
        }

}
$test = new Test();
$test->show('MyArray');
$test->add('MyArray');
$test->add('MyArray');
$test->add('MyArray');
$test->show('MyArray');

will output

Echo from Test:
Array
(
)

Fatal error: Cannot access empty property in /home/webroot/framework_devhost_dk/compiler/test2.php on line 5

For this to work properly you have to use a construct similar to this:
class Test {
        var $MyArray = array();
        function add($var) {
                $tmp =& $this->$var; //This is the trick... strange but true ;)
                $tmp[rand(1,100)] = rand(1,100);
        }
        function show($var) {
                echo "\nEcho from Test:\n";
                print_r($this->$var);
        }

}
$test = new Test();
$test->show('MyArray');
$test->add('MyArray');
$test->add('MyArray');
$test->add('MyArray');
$test->show('MyArray');

Will output:
Echo from Test:
Array
(
)

Echo from Test:
Array
(
    [19] => 17
    [53] => 57
    [96] => 43
)

rmaj (27-Sep-2007 06:52)

<?

$a = array("a"=>"111", "b"=>"222", "c"=>"333");
foreach ($a as $ix => $val) {
  $ref = &$a[$ix];
  $ref = $val . '_changed';
}

foreach ($a as $ix => $val) echo "$val ";
// 111_changed 222_changed 333_changed

?>

is a simply way to change elements of array witohut retyping $array_name[$index] all the time

riseofthethorax at gmail dot com (01-Jul-2007 11:27)

I don't see what the big fuss is, I've used pass
by reference to modify dangling variables in tree structures serializing and deserializing structures to databases.. It seems the reason for this limitation is due to the 99% PHP Newbie syndrome and their lack of pointer experience.. Note the only difference between C and PHP references is there is no pointer arithmetic.. Whether it's an alias or a memory location with the address of another, it's basically the same thing.. If you wanted I could implement tree structures in a linear resizeable array.

What am I supposed to do with
array_walk(&$datastructure,'function');
????

What am I not getting here.. What is the logic behind disabling it.. When did the PHP coders get all theoretical on us.. C is a great language because it keeps the idiots at bay, and allows you to shoot yourself in the foot if you really want to.. If I wanted to protect myself from bad code techniques I'd go write in python or lisp.

Better yet why don't we send the 99% to school to get computer science degrees.

eduardofleury at uol dot com dot br (09-Jun-2007 02:58)

<?php
$foo
= 'Hello';
$bar = 'World'
print
$foo . " " . $bar;// Hello World

$foo = &$bar;
$bar = 'Hello My World';

print
$foo;// Hello My World
print $bar;// Hello My World

?>

maghiel at mdijksman dot nl (10-May-2007 12:02)

Note that:

Call-time pass-by-reference has been deprecated - argument passed by value; If you would like to pass it by reference, modify the declaration of xxxxx. If you would like to enable call-time pass-by-reference, you can set allow_call_time_pass_reference to true in your INI file. However, future versions may not support this any longer

trucex at gmail dot com (05-May-2007 09:49)

In response to Xor and Slava:

I recommend you read up a bit more on the way PHP handles memory management. Take the following code for example:

<?php

$data
= $_POST['lotsofdata'];
$data2 = $data;
$data3 = $data;
$data4 = $data;
$data5 = $data;

?>

Assuming we post 10MB of data to this PHP file, what will PHP do with the memory?

PHP uses a table of sorts that maps variable names to the data that variable refers to in memory. The $_POST superglobal will actually be the first instance of that data in the execution, so it will be the first variable referenced to that data in the memory. It will consume 10MB. Each $data var will simply point to the same data in memory. Until you change that data PHP will NOT duplicate it.

Passing a variable by value does just what I did with each $data var. There is no significant overhead to assigning a new name to the same data. It is only when you modify the data passed to the function that it must allocate memory for the data. Passing a variable by reference will do essentially the same thing when you pass the data to the function, only modifying it will modify the data that is in the memory already versus copying it to a new location in memory.

If for learning purposes you choose to disregard the obvious pointlessness in benchmarking the difference between these two methods of passing arguments, you will need to modify the data when it is passed to the function in order to obtain more accurate results.

sneskid at hotmail dot com (06-Mar-2007 08:47)

(v5.1.4)
One cool thing about var_dump is it shows which variables are references (when dumping arrays), symbolized by '∫' for int/null, and by '&' for boolean/double/string/array/object. I don't know why the difference in symmmmbolism.
After playing around I found a better way to implement detaching (twas by accident). var_dump can show what's going on.

<?php
function &detach($v=null){return $v;}

$A=array('x' => 123, 'y' => 321);
$A['x'] = &$A['x'];
var_dump($A);
/* x became it's own reference...
array(2) {
  ["x"]=> ∫(123)
  ["y"]=> int(321)
}*/

$A['y']=&$A['x'];
var_dump($A);
/* now both are references
array(2) {
  ["x"]=> ∫(123)
  ["y"]=> ∫(123)
}*/

$z = 'hi';
$A['y']=&detach(&$z);
var_dump($A);
/* x is still a reference, y and z share
array(2) {
  ["x"]=> ∫(123)
  ["y"]=> &string(2) "hi"
}*/

$A['x'] = $A['x'];
$A['y']=&detach();
var_dump($A,$z);
/* x returned to normal, y is on its own, z is still "hi"
array(2) {
  ["x"]=> int(123)
  ["y"]=> NULL
}*/
?>

For detach to work you need to use '&' in the function declaration, and every time you call it.

Use this when you know a variable is a reference, and you want to assign a new value without effecting other vars referencing that piece of memory. You can initialize it with a new constant value, or variable, or new reference all in once step.

sneskid at hotmail dot com (01-Nov-2006 05:33)

in addition to what 'jw at jwscripts dot com' wrote about unset; it can also be used to "detach" the variable alias so that it may work on a unique piece of memory again.

here's an example

<?php
define
('NL', "\r\n");

$v1 = 'shared';
$v2 = &$v1;
$v3 = &$v2;
$v4 = &$v3;

echo
'before:'.NL;
echo
'v1=' . $v1 . NL;
echo
'v2=' . $v2 . NL;
echo
'v3=' . $v3 . NL;
echo
'v4=' . $v4 . NL;

// detach messy
$detach = $v1;
unset(
$v1);
$v1 = $detach;

// detach pretty, but slower
eval(detach('$v2'));

$v1 .= '?';
$v2 .= ' no more';
$v3 .= ' sti';
$v4 .= 'll';

echo
NL.'after:'.NL;
echo
'v1=' . $v1 . NL;
echo
'v2=' . $v2 . NL;
echo
'v3=' . $v3 . NL;
echo
'v4=' . $v4 . NL;

function
detach($v) {
   
$e = '$detach = ' . $v . ';';
   
$e .= 'unset('.$v.');';
   
$e .= $v . ' = $detach;';
    return
$e;
}
?>

output {
before:
v1=shared
v2=shared
v3=shared
v4=shared

after:
v1=shared?
v2=shared no more
v3=shared still
v4=shared still
}

http://www.obdev.at/developers/articles/00002.html says there's no such thing as an "object reference" in PHP, but with detaching it becomes possible.

Hopefully detach, or something like it, will become a language construct in the future.

gunter dot sammet at gmail dot com (09-Aug-2006 09:23)

I tried to create an array with n depth using a recursive function passing array references around. So far I haven't had much luck and I couldn't find anything on the web. So I ended up using eval() and it seems to work well:
<?php
     
foreach(array_keys($this->quantity_array) AS $key){
        if(
$this->quantity_array[$key] > 0){
         
$combinations = explode('-', $key);
         
$eval_string = '$eval_array';
          foreach(
array_keys($combinations) AS $key2){
           
$option_key_value = explode('_', $combinations[$key2]);
           
$eval_string .= '['.$option_key_value[0].']['.$option_key_value[1].']';
          }
         
$eval_string .= ' = '.$this->quantity_array[$key].';';
          eval(
$eval_string);
        }
      }
?>

This produces an n dimensional array that will be available in the $eval_array variable. Hope it helps somebody!

Xor (02-Mar-2006 03:43)

if given little - passing an array by reference slower than by value,
but not if it is necessary to process much data.

function test_ref(&$arr) {
   $size = sizeof($arr);
   for($n=0; $n<$size; $n++) {
       $x .= $arr[$n];
   }
   return $x;
}

function test_val($arr) {
   $size = sizeof($arr);
   for($n=0; $n<$size; $n++) {
       $x .= $arr[$n];
   }
   return $x;
}

// fill array
for($n=0; $n<500000; $n++) {
   $ar[] = "test".$n;
}
$Bs = array_sum(explode(' ', microtime()));
test_ref($ar);
echo "<br />The function using a reference took ".(array_sum(explode(' ', microtime()))-$Bs);
$Bs = array_sum(explode(' ', microtime()));
test_val($ar);
echo "<br />The funktion using a value took: ".(array_sum(explode(' ', microtime()))-$Bs);

The function using a reference took 10.035583019257
The funktion using a value took: 10.531390190125

Ed (22-Jan-2006 07:29)

Responding to Slava Kudinov.  The only reason why your script takes longer when you pass by reference is that you do not at all modify the array that your passing to your functions.  If you do that the diffrences in execution time will be a lot smaller.  In fact  passing by reference will be faster if just by a little bit.

Slava Kudinov <skudinov gmail com> (22-Jan-2006 10:01)

In addition to the "array vs &array" example below, php 5.1.2. It seems passing an array by reference slower than by value, consider:
<?php
function test_ref(&$arr) {
  
$size = sizeof($arr);
   for(
$n=0; $n<$size; $n++) {
      
$x = 1;
   }
}

function
test_val($arr) {
  
$size = sizeof($arr);
   for(
$n=0; $n<$size; $n++) {
      
$x = 1;
   }
}

// fill array
for($n=0; $n<2000; $n++) {
  
$ar[] = "test".$n;
}
$time = microtime();
test_ref($ar);
echo
"<br />The function using a reference took ".(microtime() - $time)." s";
$time = microtime();
test_val($ar);
echo
"<br />The funktion using a value took: ".(microtime() - $time)." s";
echo
"<br />Done";
?>
output:
The function using a reference took 0.002694 s
The funktion using a value took: 0.000847 s

cesoid at yahoo dot com (11-Dec-2005 02:28)

Responding to post from nathan (who was responding to iryoku).

It is important to note the difference between what php is doing from the programmer's point of view and what it is doing internally. The note that nathan refers to, about how (for example) $something = $this makes a "copy" of the current object, is talking about making a "copy" from the programmer's perspective. That is, for the programmer, for all practical purposes, $something is a copy, even if internally nothing has been copied yet. For example, changing the data in member $something->somethingVar will not change your current object's data (i.e. it will not change $this->somethingVar).

What it does internally is a totally different story. I've tested  "copying" an object which contains a 200,000 element array, it takes almost no time at all until you finally change something in one of the copies, because internally it only makes the copy when it becomes necessary. The original assignment takes less than a millisecond, but when I alter one of the copies, it takes something like a quarter of a second. But this only happens if I alter the 200,000 element array, if I alter a single integer of the object, it takes less than a microsecond again, so the interpretter seems to be smart enough to make copies of some of the objects variables and not others.

The result is that when you change a function to pass by reference, it will only become more efficient if, inside the function, the passed variable is having its data altered, in which case passing by reference causes your code to alter the data of the original copy. If you are passing an object and calling a function in that object, that function may alter the object without you even knowing, which means that you should pass an object by reference as long as it is ok for the original copy to be effected by what you do with the object inside the function.

I think the real moral of the story is this:
1) Pass by reference anything that should refer to and affect the original copy.
2) Pass not by reference things that will definitely not be altered in the function (for an object, it may be impossible to know whether it alters itself upon calling one of its functions).
3) If something needs to be altered inside a function without effecting the original copy, pass it not by reference, and pass the smallest practical part that needs to change, rather than passing, for example, a huge array of which one little integer will be altered.

Or a shorter version: Only pass things by reference when you need to refer to the original copy! (And don't pass huge arrays or long strings when you need to change just a small part of them!)

mramirez (at) star (minus) dev (dot) com (12-Oct-2005 05:10)

For php programmers that come from pascal,
in object pascal (delphi),
variable references are used with the "absolute" keyword.

PHP example:

<?php

global $myglobal;

$myglobal = 5;

function
test()
{
global
$myglobal;

/*local*/ $mylocal =& $myglobal;

echo
"local: " . $mylocal . "\n";
echo
"gloal: " . $myglobal . "\n";
}

test();

?>

Pascal example:

program dontcare;

var myglobal: integer;

procedure test;
var mylocal ABSOLUTE myglobal;
begin
  write("local: ", mylocal);
  write("global: ", myglobal);
end;

begin
  myglobal := 5;
  test;
end.

By the way, a "local" keyword in php for local variables,
could be welcome :-)

y007pig at yahoo dot com dot cn (07-Oct-2005 07:02)

In reply to pike at kw dot nl, '&' is only apply to PHP 4.
PHP 5 changed the behavior and the object is defaultly passed by references and if you turn on E_STRICT, you will get a notice:
Strict Standards: Assigning the return value of new by reference is deprecated in xxxx
If you want to *copy* object in PHP 5, use object clone.

pike at kw dot nl (01-Oct-2005 02:08)

if your object seems to "forget" assignments you make after instantiation, realize that in

$foo = new Bar()

the variable on the left hand is a *copy* of the variable on the right hand. As a result, & references made during instantiation may point to the righthandside version of Bar() and not to $foo. you'd better use

$foo = & new Bar()

php at REMOVEMEkennel17 dot co dot uk (24-Aug-2005 02:56)

I found a very useful summary of how references work in PHP4 (and some of the common pitfalls) in this article: http://www.obdev.at/developers/articles/00002.html

It deals with some subtle situations and I recommend it to anyone having difficulty with their references.

grayson at uiuc dot edu (12-Aug-2005 04:59)

I found a subtle feature of references that caused a bug in one of my PHP applications.  In short, if an object passes one of its members to an external function that takes a reference as an argument, the external function can turn that member into a reference to an anonymous point in memory.

Why is this a problem?  Later, when you copy the object with $a = $b, the copy and the original share memory.

Solution: If you want to have a function that uses references to modify a member of your object, your object should never pass the member to the function directly. It should first make a copy of the member. Then give that copy to the function.  Then copy the new value of that copy in to your original object member.

Below is some code that can reporoduce the this feature and demonstrate the workaround.

function modify1 ( &$pointer_obj ){
  $pointer_obj->property = 'Original Value';
}

function modify2 ( &$pointer_obj ){
  $newObj->property = 'Original Value';
  $pointer_obj = $newObj;
}

class a {
  var $i;   # an object with properties

  function corrupt1(){
    modify1 ($this->i);
  }

  function doNotCorrupt1(){
    $tmpi = $this->i;
    modify1 ($tmpi);
    $this->i = $tmpi;
  }

  function corrupt2(){
    modify2 ($this->i);
  }

  function doNotCorrupt2(){
    $tmpi = $this->i;
    modify2 ($tmpi);
    $this->i = $tmpi;
  }

}

$functions = array ('corrupt1', 'corrupt2', 'doNotCorrupt1', 'doNotCorrupt2');

foreach ($functions as $func){

  $original = new a;

  ### Load some data in to the orginal with one of the four $functions
  $original->$func();

  $copy = $original;

  $copy->i->property = "Changed after the copy was made.";

  echo "\n{$func}: \$original->i->property = '" . $original->i->property . "'";
}

The script generates output:

corrupt1: $original->i->property = 'Changed after the copy was made.'
corrupt2: $original->i->property = 'Changed after the copy was made.'
doNotCorrupt1: $original->i->property = 'Original Value'
doNotCorrupt2: $original->i->property = 'Original Value'

rlynch at lynchmarks dot com (17-May-2005 10:51)

And, further...

<?php
    $intSize
= sizeof($arrData);

    for(
$i = 0; $i < $intSize; $n++) {
      
// Do stuff
   
}
?>

Can be shortened even further by using the often overlooked 'decrement until zero' concept.  I don't much like decrementing to get a job done, but it can make a lot of sense when the evaluation-of-doneness is time-costly:

<?php
   
for($i = sizeof($arrData); $i-- > 0 ; ) {
       
// Do stuff  
   
}
?>

One less variable to toss on the heap.  NOTE that rather inconveniently, the $i goes to and hits zero only in the case where it starts out positive.  When it is zero to begin with, it will become -1.  Bug or feature?  I've used it as a feature as a quick test of whether the $arrData array was empty to begin with.  If you don't plan on using $i after the loop for anything, it makes no difference.

If you need to be doing something ascending-sequential though, then the temporary variable suggestions that others have made makes the most sense.

Finally (and important) ... if the $arrData array is somehow being dynamically modified in size due to the //Do-Stuff routine underneath, then you may have little-to-no recourse except to use the sizeof() method/function in the loop.  Or, keep up the temporary variable in the loop as you push and pop things into and off the array. 

(sigh... this is the notable failing of deeply linked internal data structures: to figure out the size of any linked list of arbitrarily composed elements, the entire array needs to be "walked" every time the sizeof() or count() method is used.  But compared to the flexibility of associative arrays, the cost is mitigated by careful use.)

GoatGuy

nslater at gmail dot com (16-Mar-2005 03:12)

In addition to the note made by "Francis dot a at gmx dot net" you should not normally be using a function such as sizeof() or count() in a control structure such as FOR because the same value is being calculated repeatedly for each iteration. This can slow things down immensely, regardless of whether you pass by value or reference.

It is generally much better to calculate the static values before the defining the looping control structure.

Example:

<?php

$intSize
= sizeof($arrData);

for(
$i = 0; $i < $intSize; $n++) {
   
// Do stuff
}

?>

Carlos (14-Mar-2005 08:09)

in the example below, you would get the same result if you change the function to something like:

function test_ref(&$arr) {
   $time = time();
   $size = sizeof($arr);       // <--- this makes difference...
   for($n=0; $n<$size; $n++) {
       $x = 1;
   }

   echo "<br />The function using a reference took ".(time() - $time)." s";
}

Francis dot a at gmx dot net (09-Feb-2005 06:53)

I don't know if this is a bug (I'm using PHP 5.01) but you should be careful when using  references on arrays.
I had a for-loop that was incredibly slow and it took me some time to find out that most of the time was wasted with the  function sizeof() at every loop, and even more time I spent  finding out that this problem it must be somehow related to the fact, that I used a reference of the array. Take a look at the following example:

function test_ref(&$arr) {
    $time = time();
    for($n=0; $n<sizeof($arr); $n++) {
        $x = 1;
    }
    echo "<br />The function using a reference took ".(time() - $time)." s";
}

function test_val($arr) {
    $time = time();
    for($n=0; $n<sizeof($arr); $n++) {
        $x = 1;
    }
    echo "<br />The funktion using a value took: ".(time() - $time)." s";
}

// fill array
for($n=0; $n<2000; $n++) {
    $ar[] = "test".$n;
}

test_ref($ar);
test_val($ar);
echo "<br />Done";

When I tested it, the first function was done after 9 seconds, while the second (although the array must be copied) was done in not even one.

The difference is inproportional smaller when the array size is reduced:
When using 1000 loops the first function was running for 1 second, when using 4000 it wasn't even done after 30 Seconds.

jw at jwscripts dot com (16-Oct-2004 01:18)

Re-using variables which where references before, without unsetting them first, leads to unexpected behaviour.

The following code:

<?php

$numbers
= array();

for (
$i = 1; $i < 4; $i++) {
   
$numbers[] = null;
   
$num = count($numbers);
   
$index =& $numbers[$num ? $num - 1 : $num];
   
$index = $i;
}

foreach (
$numbers as $index) {
    print
"$index\n";
}

?>

Does not produce:
1
2
3

But instead:
1
2
2

Applying unset($index) before re-using the variable fixes this and the expected list will be produced:
1
2
3

hkmaly at bigfoot dot com (15-Sep-2004 04:11)

It seems like PHP has problems with references, like that it can't work properly with circular references or free properly structure with more references. See http://bugs.php.net/?id=30053.

I have big problem with this and I hope someone from PHP add proper warning with explanation IN manual, if they can't fix it.

jlaing at gmail dot com (18-Jul-2004 04:28)

While trying to do object references with the special $this variable I found that this will not work:
class foo {
  function bar() {
    ...
    $this =& $some_other_foo_obj;
  }
}

If you want to emulate this functionality you must iterate through the vars of the class and assign references like this:

$vars = get_class_vars('foo');
foreach (array_keys($vars) as $field) {
  $this->$field =& $some_other_foo_obj->$field;
}

Now if you modify values within $this they will be modified within $some_other_foo_obj and vice versa.

Hope that helps some people!

p.s.
developer at sirspot dot com's note about object references doesn't seem correct to me.

  $temp =& $object;
  $object =& $temp->getNext();

Does the same exact thing as:

  $object =& $object->getNext();

when you refernce $temp to $object all it does is make $temp an alias to the same memory as $object, so doing $temp->getNext(); and $object->getNext(); are calling the same function on the same object.  Try it out if you don't believe me.

thenewparadigm at hotmail dot com (07-May-2004 08:33)

one very useful aspect for reference that i don't think i saw documented was the ability to skip a few steps with objects stored in objects.

for example:

assuming the object structure is correctly constructed (and mind you i haven't tried this in php, but it does work in most other high-end programming languages), instead of using this structure to get a variable/function

//start

$obj1 -> obj2 -> obj3 -> varX = 0;
$obj1 -> obj2 -> obj3 -> varY = 0;
$obj1 -> obj2 -> obj3 -> functionX();
$obj1 -> obj2 -> obj3 -> functionY();

//end

you can use this method:

//start

$tempObj = & $obj1 -> obj2 -> obj3;

$tempObj -> varX = 0;
$tempObj -> varY = 0;
$tempObj -> functionX();
$tempObj -> functionY();

//end

note, if you want to use a shortcut variable to modify the original object you must include the ampersand (&) to reference the variable, otherwise if you used this line of code

//start

$tempObj = $obj1 -> obj2 -> obj3;

//end

any changes you make to $tempObj will not change the original object and may compromise the object structure, not to mention that it takes up extra memory.  however, if you are just using the shortcut variable for read-only purposes, not using a reference wont cause any problems.

another alternative in programming languages is the 'with' structure as seen below

//start

with($obj1 -> obj2 -> obj3) {
    varX = 0;
    varY = 0;
    functionX();
    functionY();
}

//end

however, i don't expect this will work because as far as i've seen the 'with' structure is not supported in php.

nathan (06-Apr-2004 06:53)

On the post that says php4 automagically makes references, this appears to *not* apply to objects:

http://www.php.net/manual/en/language.references.whatdo.php

"Note:  Not using the & operator causes a copy of the object to be made. If you use $this in the class it will operate on the current instance of the class. The assignment without & will copy the instance (i.e. the object) and $this will operate on the copy, which is not always what is desired. Usually you want to have a single instance to work with, due to performance and memory consumption issues."

iryoku at terra dot es (30-Mar-2004 06:22)

You should have in mind that php4 keep assigned variables "automagically" referenced until they are overwritten. So the variable copy is not executed on assignment, but on modification. Say you have this:

$var1 = 5;
$var2 = $var1; // In this point these two variables share the same memory location
$var1 = 3; // Here $var1 and $var2 have they own memory locations with values 3 and 5 respectively

Don't use references in function parameters to speed up aplications, because this is automatically done. I think that this should be in the manual, because it can lead to confusion.

More about this here:
http://www.zend.com/zend/art/ref-count.php

developer at sirspot dot com (03-Feb-2004 06:30)

Since references are more like hardlinks than pointers, it is not possible to change a reference to an object by using that same reference.  For example:

The following WILL NOT WORK as expected and may even crash the PHP interpreter:

$object =& $object->getNext();

However, by changing the previous statement to use a temporary reference, this WILL WORK:

$temp =& $object;
$object =& $temp->getNext();