你是否应该通过引用建立一个'事先变量?

时间:2017-01-19 10:38:17

标签: php pass-by-reference

PHP文档中的示例:

http://php.net/manual/en/function.openssl-public-encrypt.php

openssl_public_encrypt ( 
    string $data , string &$crypted , mixed $key [, int $padding =         
    OPENSSL_PKCS1_PADDING ] 
)

在这种情况下,它希望$ crypted作为传递引用。该功能无需预先设置$ crypted即可使用。

在很多例子中,我看到$ crypted在调用函数之前被初始化。

var $crypted = '';

这是否真的需要(或技术上更正确),或者没有设置变量就好了,即使它是通过引用传递的#39;变量?

2 个答案:

答案 0 :(得分:1)

虽然将创建变量,但我更倾向于明确地设置它,原因如下:

  • 该变量可能在函数中用于从中获取数据
  • 可能未在函数中设置变量,因此我之后不需要打扰isset
  • 该变量可能已在代码中的其他位置定义,因此如果函数未更改变量,则存在传递垃圾或接收垃圾的风险
  • 我必须提到其他一些我忘记提及的内容,所以让我们把它命名为直觉

不确定其中是否有任何一个特别适用于openssl_public_encrypt,但由于您习惯于在函数调用之前设置变量,因此更改此行为需要更多的努力和关注。

答案 1 :(得分:1)

更多的评论而不是答案 - 但评论框太长了。还有一个令人着迷的问题让我问起为什么"。

直接回答:

  • 不声明变量不会导致" NOTICE"在任何一个版本中 - 所以在技术上它不是必需的。
  • 因此宣布是优先事项。与Alex一样,我更愿意声明其可读性和清晰度。 (我也更喜欢避免像extract这样的函数从no-where创建变量。)但我确信其他人会不同意。

但这导致了为什么它的作用是这样的问题?而且我很想知道。

首先要注意的是,通过引用传递的变量和变量从PHP 5变为PHP 7.这里有一个有趣的读物:https://nikic.github.io/2015/05/05/Internal-value-representation-in-PHP-7-part-1.html解释了差异。

但是在两个PHP中,变量都存储在zval空间中,并带有引用变量的引用计数器。 (上面的文档是我在解释它时发现的最好的例子,但manual中还有更多

扩展PHP并添加新函数时,可以使用zend_parse_parameters从Zend API获取变量。这意味着传递给函数的变量也存储在zval容器中,并在API和扩展之间传递。 (Further reading - 这与PHP5有关,但对PHP7来说却是一样的。

我的理解(我很乐意纠正)在四个代码示例中进行了解释:

1)

function increment($i) {
    $i++;
}

increment(3);

变量3未声明(显然),但它需要位于zval容器中才能传递给API。这表明调用函数具有在zval容器中生成变量的能力。 (因为它不是一个真正的变量,我认为它是不可思议的"但这是一个猜测。)

2)

function increment($i) {
    $i++;
}

increment($y);

$y错误未首先声明。 Notice: Undefined variable: y in test.php。因此,它无法生成$y并放入本地范围。

3)

function increment($i) {
    $i++;
}

$y = 0;
increment($y);

声明变量并将其放入zval容器中。调用函数时,refcount将会增加,因此可以传递给API。按预期工作。

4)

function increment(&$i) {
    $i++;
}

increment(3);

此错误Fatal error: Only variables can be passed by reference in test.php。这告诉我们变量3zend_parse_parameters拒绝,因为它知道它是不可变的,或者调用函数知道函数需要通过引用变量。

5)

function increment(&$i) {
    $i++;
}

$y = 0;
increment($y);

变量$y被放入第一行当前作用域的zval容器中,并生成指向$y的引用指针(增加refcount两次)。

6)

function increment(&$i) {
    $i++;
}

increment($y);

这是梨形状的地方IMO:虽然没有声明变量,但是$y == 1。这意味着该函数必须创建变量并将其放入当前作用域中的zval容器中,并生成指向$y的引用指针(增加refcount)。

要做到这一点,它必须知道函数是通过引用期望值 - 否则为什么行为与2不同?

这一切都没有解释为什么它与众不同。仅仅因为它可以创建一个变量(如例1所示),为什么它不是在例2中,但它在例6中呢?