PHP数组引用的深层副本

Cha*_*had 17 php deep-copy

所以$ array是一个数组,其中所有元素都是引用.

我想将这个数组追加到另一个名为$ results的数组(在循环中),但由于它们是引用,PHP复制引用,$ results充满了相同的元素.

到目前为止,最佳工作解决方案是:

$results[] = unserialize(serialize($array));
Run Code Online (Sandbox Code Playgroud)

我担心这会非常低效.有一个更好的方法吗?

Lep*_*eus 9

你可以在返回时使用函数解引用结果这一事实,例如,这里$array_by_myclone仍然会引用$original($array_by_myclone[0][0] == 'foo')而$array_by_assignment有一个克隆值($array_by_assignment[0][0] == 'bar')

$original = 'foo';
$array_of_reference = array(&$original);

function myclone($value)
{
  return $value;
}

$array_by_myclone = array();
$array_by_myclone[] = array_map('myclone', $array_of_reference);

$array_by_assignment = array();
$array_by_assignment[] = $array_of_reference;

$original = 'bar';

var_dump($array_by_myclone[0][0]); // foo, values were cloned                                                                                                                                   
var_dump($array_by_assignment[0][0]); // bar, still a reference                     
Run Code Online (Sandbox Code Playgroud)

编辑:我想检查评论说unserialize(serialize())是否更快是正确的,所以我使用PHP 5.5进行测试,结果证明这是错误的:即使使用小数据集,使用序列化方法也会更慢,并且您拥有的数据越多变慢了.

lepidosteus@server:~$ php -v
PHP 5.5.1-1~dotdeb.1 (cli) (built: Aug  3 2013 22:19:30) 
Copyright (c) 1997-2013 The PHP Group
Zend Engine v2.5.0, Copyright (c) 1998-2013 Zend Technologies
    with Zend OPcache v7.0.2-dev, Copyright (c) 1999-2013, by Zend Technologies
lepidosteus@server:~$ php reference.php 1
myclone:   0.000010 seconds
serialize: 0.000012 seconds
lepidosteus@server:~$ php reference.php 1000000
myclone:   0.398540 seconds
serialize: 0.706631 seconds
Run Code Online (Sandbox Code Playgroud)

使用的代码:

<?php
$iterations = 1000000;
if (isset($argv[1]) && is_numeric($argv[1])) {
  $iterations = max(1, (int)$argv[1]);
}

$items = array();
for ($i = 0; $i < $iterations; $i++) {
  $items[] = 'item number '.$i;
}

$array_of_refs = array();
foreach ($items as $k => $v) {
  $array_of_refs[] = &$items[$k];
}

function myclone($value)
{
  return $value;
}

$start = microtime(true);

$copy = array_map('myclone', $array_of_refs);

$time = microtime(true) - $start;

printf("%-10s %2.6f seconds\n", 'myclone:', $time);

$start = microtime(true);

$copy = unserialize(serialize($array_of_refs));

$time = microtime(true) - $start;

printf("%-10s %2.6f seconds\n", 'serialize:', $time);
Run Code Online (Sandbox Code Playgroud)

  • 我做了一些基准测试和反序列化(serialize())稍微快一些 (7认同)
  • 序列化比array_map更快是非常值得怀疑的.也许如果你的数组只是一个很长的几个元素. (4认同)