让我说我有一个数组(它实际上可以有任何深度):
$arr = array(
"lvl1" => array(
"lvl2 => ...
)
)
现在在函数中,我需要像这样访问它:
$path = array("lvl1", "lvl2", ...); // array of ordered indexes
$tmp = $arr;
foreach($path as $lvl){
...// other read-only/copy stuff happening on the array, no editing
$tmp = $tmp[$lvl];
}
在这一点上,出于好奇(这里没有真正的优化),我是否每次都制作份副本?还是只是自动使用引用?
答案 0 :(得分:2)
TL; DR如果您使用的是PHP 7,除非您进行更改,否则不会在内部复制该数组。这称为写时复制。
要了解PHP的工作原理,您可以阅读Reference Counting Basics:
PHP变量存储在称为“ zval”的容器中。
PHP足够聪明,不必在不需要时复制实际的变量容器。
让我们尝试使用debug_zval_dump
在简化示例中对此进行说明:
$array = [
'lvl1' => [
'lvl2' => [
'lvl3' => [
],
],
],
];
$path = ['lvl1', 'lvl2', 'lvl3'];
$tmp = $array;
foreach ($path as $lvl) {
debug_zval_dump($array);
$tmp = $tmp[$lvl];
}
debug_zval_dump($array);
如果运行此代码,您将获得以下输出:
array(1) refcount(4){
["lvl1"]=>
array(1) refcount(1){
["lvl2"]=>
array(1) refcount(1){
["lvl3"]=>
array(0) refcount(1){
}
}
}
}
array(1) refcount(3){
["lvl1"]=>
array(1) refcount(2){
["lvl2"]=>
array(1) refcount(1){
["lvl3"]=>
array(0) refcount(1){
}
}
}
}
array(1) refcount(3){
["lvl1"]=>
array(1) refcount(1){
["lvl2"]=>
array(1) refcount(2){
["lvl3"]=>
array(0) refcount(1){
}
}
}
}
array(1) refcount(3){
["lvl1"]=>
array(1) refcount(1){
["lvl2"]=>
array(1) refcount(1){
["lvl3"]=>
array(0) refcount(2){
}
}
}
}
请注意refcount
:它会发生变化,因此在内部PHP会通过引用进行分配,直到您实际更改分配的值为止。您可以在the blog post by nikic中阅读有关内容:
与PHP 5的重要区别在于,即使有些变量是PHP引用,而有些不是PHP引用,所有变量都可以共享同一数组。只有执行某种修改后,阵列才会被分离。