PHP访问嵌套数组时是否会进行数组复制?
关于PHP多维数组遍历访问时的副本/引用问题
嘿,这个问题问得相当有意思!正好可以聊聊PHP数组里非常关键的**写时复制(Copy-on-Write,COW)**机制——这就是决定你代码行为的核心。
先直接给结论:在你这段只读操作的代码里,完全不会生成数组副本,PHP会自动用内部的引用优化来避免不必要的内存开销。
具体细节拆解:
- 默认情况下PHP数组是「值语义」,但它有个聪明的优化逻辑:只有当你尝试修改数组的时候,才会真正复制内存。
- 当你执行
$tmp = $arr时,PHP并没有把整个数组复制一份,只是让$tmp和$arr共享同一块内存,同时标记为「只读共享」状态。 - 接下来的
foreach循环里,$tmp = $tmp[$lvl]只是让$tmp指向原数组里的对应子数组节点,全程没有任何修改操作,所以PHP完全没必要复制数组——它只是调整了内部的指针指向,内存占用几乎没有变化。
验证小例子(用内存变化直观感受):
你可以用memory_get_usage()来测试这个过程:
$arr = ['lvl1' => ['lvl2' => ['lvl3' => 'test']]]; $path = ['lvl1', 'lvl2']; echo '初始内存占用: ' . memory_get_usage() . PHP_EOL; $tmp = $arr; echo '赋值$tmp后内存: ' . memory_get_usage() . PHP_EOL; // 和初始值几乎一致,无复制 foreach($path as $lvl) { $tmp = $tmp[$lvl]; echo "访问{$lvl}后内存: " . memory_get_usage() . PHP_EOL; // 内存变化极小,无数组复制 } // 现在尝试修改$tmp,触发写时复制 $tmp['new_key'] = 'new_val'; echo '修改$tmp后内存: ' . memory_get_usage() . PHP_EOL; // 内存明显上涨,此时才生成了副本
补充说明:
只有当你对$tmp或者原数组$arr执行修改操作(比如赋值、unset、排序等)时,PHP才会立即复制一份独立的数组出来,确保修改不会影响到共享的原数组。而你的代码全程是只读/指针指向操作,所以完全不会触发副本生成。
内容的提问来源于stack exchange,提问作者Xriuk
相关产品推荐
相关产品推荐

