错误消息“严格的标准:只能通过引用传递变量”

Posted

技术标签:

【中文标题】错误消息“严格的标准:只能通过引用传递变量”【英文标题】:Error message "Strict standards: Only variables should be passed by reference" 【发布时间】:2011-01-22 05:08:34 【问题描述】:
$el = array_shift($instance->find(..))

上面的代码以某种方式报告了严格标准的警告,但这不会:

function get_arr()
    return array(1, 2);

$el = array_shift(get_arr());

那么它什么时候会报告警告呢?

【问题讨论】:

$instance->find(..) 返回什么? 这里是解决方案:***.com/questions/9848295/… 我认为示例(或逻辑)可能是问题中的错误方式,因为第二个示例(get_arr() 函数)确实产生了严格的标准通知(测试 php 5.2 和 PHP 5.5)。 【参考方案1】:

考虑以下代码:

error_reporting(E_STRICT);
class test 
    function test_arr(&$a) 
        var_dump($a);
    
    function get_arr() 
        return array(1, 2);
    


$t = new test;
$t->test_arr($t->get_arr());

这将生成以下输出:

Strict Standards: Only variables should be passed by reference in `test.php` on line 14
array(2) 
  [0]=>
  int(1)
  [1]=>
  int(2)

原因? test::get_arr() 方法不是变量,在严格模式下会产生警告。这种行为非常不直观,因为get_arr() 方法返回一个数组值。

要在严格模式下解决此错误,请更改方法的签名以使其不使用引用:

function test_arr($a) 
    var_dump($a);

由于您无法更改array_shift 的签名,您也可以使用中间变量:

$inter = get_arr();
$el = array_shift($inter);

【讨论】:

@user198729:我也在寻找解释或修复,发现您可以将 current() 用于第一项。唉 end() 不适用于最后一个,因为它“将内部指针推进到最后一个元素”。 current(array_reverse(somefunction())) 有效(是的,这很傻) 使用current 假设数组指针位于第一个元素处。在大多数情况下,这可能是一个有效的假设,但需要注意。 @leepowers 当然,那么会有与array_shift() 相同的问题,因为它希望引用修改:-) @user198729 您可以通过使用额外的括号来避免$intermediate 值。 $el = array_shift( ( get_arr() ) );。见***.com/questions/9848295/… @Chloe 这是我见过的保持代码简单的最出色的解决方案!谢谢!【参考方案2】:

$instance->find() 返回对变量的引用。

当您尝试将此引用用作函数的参数时,您会得到报告,而不是先将其存储在变量中。

这有助于防止内存泄漏,并且可能会在下一个 PHP 版本中成为错误。

如果您的第二个代码块这样写(注意函数签名中的&),则会引发错误:

function &get_arr()
    return array(1, 2);

$el = array_shift(get_arr());

所以一个快速(但不是很好)的解决方法是:

$el = array_shift($tmp = $instance->find(..));

基本上,您首先对临时变量进行赋值,然后将该变量作为参数发送。

【讨论】:

它现在应该可以工作了(检查过)。为了返回引用,您必须在方法签名处声明它,而不是返回语句(我的错)。 不,我不能更改签名。@pygorex1 的中间变量可以解决这个问题,但看起来是多余的,不是吗? 我知道您不能更改签名,只是解释了它是如何发生的。您必须使用临时(=中间)变量,但您可以在同一行中执行此操作。看我的第二个代码 sn-p。 我试过你的第二个 sn-p,不工作。它只能在单独的行中工作 确实如此。赋值返回分配的值array_shift($tmp = $instance->find(..))$instance->find(..) 的值分配给$tmp,然后将分配的值 传递给array_shift()——这与传递$tmp 本身不同,所以是不比没有分配的原始情况好。【参考方案3】:

错误原因是使用了PHP内部的编程数据结构函数array_shift() [php.net/end]。

该函数接受一个数组作为参数。虽然在“手册”中array_shift() 的原型中指出了一个&,但在该函数的扩展定义中没有任何警示性文档,也没有任何明显的解释表明该参数实际上是通过引用传递的。

也许这是/理解/。但是我不明白,所以我很难发现错误的原因。

重现代码:

function get_arr()

    return array(1, 2);

$array = get_arr();
$el = array_shift($array);

【讨论】:

【参考方案4】:

这段代码:

$monthly_index = array_shift(unpack('H*', date('m/Y')));

需要改成:

$date_time = date('m/Y');
$unpack = unpack('H*', $date_time);
array_shift($unpack);

【讨论】:

【参考方案5】:

第二个 sn-p 也不起作用,这就是原因。

array_shift 是一个修饰函数,它改变了它的参数。因此它期望它的参数是一个引用,并且你不能引用不是变量的东西。请在此处查看 Rasmus 的解释:Strict standards: Only variables should be passed by reference

【讨论】:

【参考方案6】:

好吧,在这种明显的情况下,您总是可以通过在函数前面使用“@”来告诉 PHP 隐藏消息。

$monthly_index = @array_shift(unpack('H*', date('m/Y')));

以这种方式抑制所有错误可能不是最佳编程实践之一,但在某些情况下(如本例)它很方便并且是可以接受的。

因此,我相信您的朋友“系统管理员”会对污染较少的error.log 感到满意。

【讨论】:

我不知道谁对这个答案投了反对票,但提出的解决方案确实有效,而且它是一种 PHP 标准技术。真令人失望……下次我可能不再回答问题了……:( 我认为这是因为抑制错误消息并不能解决代码问题。当这种类型的错误在未来的 PHP 版本中从 E_STRICT 变为 E_ERROR 并且您的代码现在无法运行并且也不会产生任何错误/输出时,您会怎么做? @TinoDidriksen,我理解并同意反对一些“坏习惯”的理由,尤其是对于新一代。但是,当(以及是否)可以安全使用并适用于建议的上下文时,可以使用资源。如果要废除错误抑制器“@”,它就会从语言本身中删除。与 "eval" 相同(它可能是邪恶的,但它有其目的)。我反对的不是某些资源的使用,而是建议的概括。特别是对于提议的案例,使用它不会有任何危害,即使是出于调试目的。

以上是关于错误消息“严格的标准:只能通过引用传递变量”的主要内容,如果未能解决你的问题,请参考以下文章

react组件传参(消息订阅与发布机制)

谁能说一下C语言参数传值和传引用是啥概念,谢谢!:)?

PHP引用传值规范问题

构建消息错误时的 ARC 弱引用

通过引用将向量对象传递给函数? [关闭]

引用 .dll 文件时出现错误消息