简体   繁体   中英

PHP Array reference confusion

With this code:

$a[1]=1;
$a[2]=& $a[1];

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

print_r($a);

I was expecting output to be 1 because $a is not assigned by reference to $b ( $a = & $b ) but it comes out to be 7 . Why?

You're copying the array by value, but the elements of the source array are references. These references are just shallow-copied to the destination.

php > var_dump($a);
array(2) {
  [1]=>
  &int(1)
  [2]=>
  &int(1)
}
php > $b=$a;
php > var_dump($b);
array(2) {
  [1]=>
  &int(1)
  [2]=>
  &int(1)
}

Here's an example copying the array by reference:

php > $c[1] = 1;
php > $c[2] =& $c[1];
php > var_dump($c);
array(2) {         
  [1]=>            
  &int(1)
  [2]=>
  &int(1)
}
php > $d =& $c;
php > var_dump($d);
array(2) {
  [1]=>
  &int(1)
  [2]=>
  &int(1)
}
php > $d = array(3,4,5);
php > var_dump($c);
array(3) {
  [0]=>
  int(3)
  [1]=>
  int(4)
  [2]=>
  int(5)
}
php > var_dump($d);
array(3) {
  [0]=>
  int(3)
  [1]=>
  int(4)
  [2]=>
  int(5)
}

As you can see, the array variable (not elements) itself is a reference, so modifying $d affects $c . Reassigning $b itself has no effect on $a .

That's how references work. What are you saying when you do $a[2]=& $a[1]; is that both elements of $a now hold the same variable. When you do $b = $a, $b and $a are different variables, but all 4 elements inside them point to the same variable! Try doing $b[3] = 7 and see it's not copied to $a - because $b and $a are different, but $b[2] and $a[2] are not!

References are a bit messy, sorry. Avoid using them unless you must.

This help me to understand what references are:

http://www.php.net/manual/en/features.gc.refcounting-basics.php

http://books.google.com/books?id=e7D-mITABmEC&pg=PT171&lpg=PT171&dq=php+object+zval&source=bl&ots=oawmzMtsXt&sig=mMSuVKsk6L3JWuEikJN8j7dQfRs&hl=ru&ei=JmDWTOraI4TNswaDt-jkCA&sa=X&oi=book_result&ct=result&resnum=10&ved=0CEcQ6AEwCQ#v=onepage&q=php%20object%20zval&f=false

And debugging with xdebug of interesting cases helps too

For example you can "avoid" private properties:

class c{
    private $a = 42;
    function &a(){
        return $this->a;
    }
    function print_a(){
        echo $this->a;
    }
}
$c = new c;
$d = &$c->a();
echo $d;
$d = 2;
$c->print_a();

or pass by reference to functions if you not declared it:

function f1(&$s) {
    $s++;
}
function f2($s) {
    $s--;
}
$s1 = 1;
$s2 = 3;
f1($s1);
f2(&$s2);
echo $s1.$s2;

also foreach can use pass-by-reference

$a = array(1,2,3); foreach ( $a as $key => &$value ) { $value = 1; } $value = 2;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM