首頁  >  問答  >  主體

php - foreach既然是操作原數組的副本,為什麼這樣寫還能改變原數組呢

foreach循環使用的是原始數組的拷貝,為什麼這樣引用賦值後就能改變原始數組?

$aOriginArray为二维数组
Array
(
    [0] => Array
        (
            [test1] => 1
            [test2] => 2
        )
)
foreach($aOriginArray as &$aNewValue){
    //为原数组子数组添加一个元素
    $aNewValue['new'] = 3;
}
//经过foreach循环引用赋值方式修改数组后的结果
print_r($aOriginArray);
Array
(
    [0] => Array
        (
            [test1] => 1
            [test2] => 2
            [new]   => 3 
        )
)

這段可以證明foreach操作的是原數組的副本,
而且原數組同步時被丟在了半路上,原數組的內部指針只移動了一次,
後續的操作都是在副本上執行的

$k = ['a','b','c'];

foreach($k as $t){
    echo "current:".current($k);
    echo "<br>";
    echo "foreach:".$t;
    echo "<br>";
}
输出的结果是:
current:b
foreach:a
current:b
foreach:b
current:b
foreach:c

在使用引用賦值時,陣列的引用情況如下


xdebug_debug_zval("k");

k:
(refcount=2, is_ref=1),

数组的引用计数为2,说明有两个变量指向同一个数组,is_ref值为1,说明数组被引用
也就是说foreach在引用赋值时操作的是原数组,此时没有产生数组的拷贝
foreach的第一个参数为原数组的别名

foreach($k as &$t){
    ...
}

当使用foreach($k as $t){...}不加引用
数组的引用情况如下
k:
(refcount=1, is_ref=0),

原数组仅有一个符号在指向且未被引用

非常感謝以下各位的耐心回答

三叔三叔2675 天前1035

全部回覆(4)我來回復

  • 给我你的怀抱

    给我你的怀抱2017-06-22 11:55:30

    你加了&符號後不是使用的是原始數組的拷貝。不加&符號確實是原始數組的拷貝。加&符號相當於一個指針,把名字賦給它而已。所以你改變你新的數組,原來的數組也會改變。
    自 php 5 起,可以輕鬆地透過在 $value 之前加上 & 來修改陣列的單元。此方法將以引用賦值而不是拷貝一個值。

    <?php
    $arr = array(1, 2, 3, 4);
    foreach ($arr as &$value) {
        $value = $value * 2;
    }
    // $arr is now array(2, 4, 6, 8)
    ?>

    回覆
    0
  • 習慣沉默

    習慣沉默2017-06-22 11:55:30

    你加了傳地址符號 & 後 $aNewValue 就變成了指向了數組裡每一個元素的指針,相當於修改原數組

    回覆
    0
  • phpcn_u1582

    phpcn_u15822017-06-22 11:55:30

    php是寫時複製的吧,拷貝的時候只是用一個新的指標指向值而已,

    回覆
    0
  • PHP中文网

    PHP中文网2017-06-22 11:55:30

    就是一個變數的引用詶,兩個變數指向同一個位址,操作副本也是修改原數組

    回覆
    0
  • 取消回覆