【问题标题】:PHP function array_replace(), why are the arguments passed by reference?PHP函数array_replace(),为什么参数是通过引用传递的?
【发布时间】:2012-06-24 19:51:19
【问题描述】:

PHP.net 上的 array_replace() 函数签名表明数组将通过引用传入。这样做的原因/好处是什么,而不是按值这样做,因为要获得预期的结果,您必须将完成的数组返回给变量。为了清楚起见,我能够重现手册中的结果,所以这不是关于如何使用此功能的问题。

这是函数签名和示例,均来自 php.net。

来源:http://ca3.php.net/manual/en/function.array-replace.php

函数签名:

array array_replace ( array &$array , array &$array1 [, array &$... ] )

示例代码:

$base = array("orange", "banana", "apple", "raspberry");
$replacements = array(0 => "pineapple", 4 => "cherry");
$replacements2 = array(0 => "grape");

$basket = array_replace($base, $replacements, $replacements2);
print_r($basket);

上面的例子会输出:

Array
(
    [0] => grape
    [1] => banana
    [2] => apple
    [3] => raspberry
    [4] => cherry
)

【问题讨论】:

  • @biziclop 那篇文章真是长篇大论。他非常坦率地表示不喜欢 PHP,所以这篇文章当然对它持负面偏见。并不意味着他是 100% 正确的。
  • 顺便说一句,array_replace 的文档页面最近已更新 - 我们一直在谈论的错误现在已经消失了。所以我想我们毕竟可以让这个世界变得更美好。 )

标签: php arrays php-5.3


【解决方案1】:

This function 调用php_array_merge_or_replace_wrapper 调用zend_hash_merge 又调用_zend_hash_merge 等等等等等等导致底层的memcmp() 调用,这可能是数组被传递到PHP 的@987654327 的最终原因@ 引用(因为memcmp() 要求它们是)。

数组是 PHP 的一个方面,它似乎只是工作并且很少受到质疑,经过一番挖掘,我可以明白为什么。

【讨论】:

  • 你的意思可能是into PHP's array_replace() by reference - array_merge() signature 是官方无参考的。 )
  • @Crontab 感谢您的回答。我现在明白了。
  • 人们赞成这个是因为他们熟悉 php 的内部工作原理,所以你同意整个 memcmp 的事情吗?我不买...
  • @rambocoder 您是否阅读了代码链接?他们直接转到 PHP 的源代码(memcmp() 链接转到 GNU 的 libc 手册),我不确定还有哪些其他参考资料更权威...
  • @rambocoder PHP 源代码中很少有 cmets 来解释他们为什么选择以他们的方式做事。我认为我不应该仅仅因为我没有打电话给拉斯穆斯并要求他解释自己而投反对票。
【解决方案2】:

嗯,重点是 _zend_hash_merge 函数不仅被 array_merge 使用 - 也被 + operator 使用(当它的两个操作数都是数组时)。

虽然在处理上有一些差异,但实际上没有一个可以归因于需求的差异:据我所知,没有人将+ 写成&$arr + &$arr,这毫无意义。

所以我想这只是文档中的一个错误。

但是如果不分析 PHP 内部代码的深渊,就可以得出这个结论。 ) 请记住,当我们传递一个可以(并且很可能会)改变的数组时,我们使用&$array 表示法——例如,参见array_splice() 签名。而且(这可以很容易地检查)array_replace 不会改变它的论点——至少目前是这样。 )

更新:好吧,现在我很生气。如果某个 PHP 开发人员,上帝保佑他的灵魂,实际上认为这不是文档中的错误,让他/她解释一下原因:

array_pop(array('a' => 1));

...触发致命错误 (Only variables can be passed by reference),而这...

array_replace(array('a' => 1), array('b' => 2));

... 会正常工作,因为什么都没发生。

或者我们现在在 PHP 中有两种类型的引用吗?

【讨论】:

  • 我还以为是bug,所以我提交了一个bug,有人回复说这不是bug,因为函数按照文档中的描述工作。但它也在文档中说“您可以通过引用函数来传递变量,以便函数可以修改变量”。
  • 更新了答案。太棒了:每次我认为 PHP 支持社区不会再让我感到惊讶时,它只是设法做到了。
  • php 并不总是抱怨这一点。例如 current(array(1)); 但是...我认为 current() 只是被误记录为需要参考。
【解决方案3】:

这是一个文档错误,现已修复。

https://bugs.php.net/bug.php?id=62383

【讨论】:

    【解决方案4】:

    假设:

    由于按值传递涉及复制数组,我想通过引用传递它们会更快。

    测试一下:

    <?php 
    
    function ref(array &$array) {
        for($i = 0; $i < count($array); $i++) {
            $array[$i] == 'foo'; //just accessing
        }
    }
    
    function val(array $array) {
        for($i = 0; $i < count($array); $i++) {
            $array[$i] == 'foo'; //just accessing
        }
    }
    
    
    //create large array
    $array = array();
    for($i = 0; $i < 100; $i++) {
        $array[] = $i;
    }
    
    
    echo "Pass by reference\n";
    $t1 = microtime(true);
    for($i = 0; $i < 10000; $i++) {
        ref($array);
    }
    $t2 = microtime(true);
    echo $t2 - $t1 . "s\n\n";
    
    echo "Pass by value\n";
    $t1 = microtime(true);
    for($i = 0; $i < 10000; $i++) {
        val($array);
    }
    $t2 = microtime(true);
    echo $t2 - $t1 . "s\n\n";
    

    输出:

    Pass by reference
    8.3282010555267s
    
    Pass by value
    1.4845979213715s
    

    结论:

    显然不是出于性能原因。

    【讨论】:

    • 尝试调用ref(array('a' =&gt; 1))val(array('a' =&gt; 1))。看到小 &amp; 符号的区别了吗? )
    • @raina77ow - 实际上,通过引用传递似乎更慢(看看测试结果),所以整个it's for performance 的想法无论如何都是错误的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-04-05
    • 2020-04-13
    • 2020-10-02
    • 1970-01-01
    • 2020-12-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多