我到处都是混合信号。
我是否使用&符号通过引用传递变量?
以下链接似乎告诉我它已被弃用且不再需要:
http://gtk.php.net/manual/en/html/tutorials/tutorials.changes.references.html
但这些线索让我想知道:
Call-time pass-by-reference deprecated?
PHP and ampersand
让我以我的问题为例。
如果我使用PHP 5.5.5创建函数:
function recurring_mailer_form($form, $form_state)
{
}
是否与:
相同function recurring_mailer_form($form, &$form_state)
{
}
答案 0 :(得分:22)
不同文章似乎在说不同的事情的原因是他们在谈论不同类型的传递参考。
决定参数是否应该通过引用传递的主要因素是函数签名本身,自PHP 4以来,其基本原理没有改变。考虑这个例子:
function foo( $by_value, &$by_reference ) { /* ... */ }
$a = 1; $b = 2;
foo( $a, $b );
此处,外部变量$a
将按值传递给函数,就好像它被指定为$by_value = $a;
一样 - 对$by_value
的更改不会影响$a
。然而,变量$b
通过引用传递 ;就像$by_reference =& $b;
形式的赋值一样,这意味着有两个名称引用了一个变量,对一个名称的任何赋值都将作为两者的赋值。
如果按值传递“普通”值(字符串,数字或数组),则只将其值复制到新变量中。 从PHP 5开始:如果按值传递对象,则会发生稍微不同的事情 - 复制的“值”只是指向同一对象的指针。这意味着,如果$a
是对象,则可以调用$by_value->some_property = 42;
,$a->some_property
也可以是42
。但是,如果您为$by_value
分配了一些新值,则仍然不会影响$a
。
直到PHP 5.4 ,有一种额外的方式通过引用传递参数,这是为了“强制”参与行为在调用时< / em>的。这意味着您可以在foo(&$a, &$b);
函数内写$by_value
并“捕获”对foo()
所做的更改。依赖于此通常是一个坏主意,因此它被删除。 (它落在5.4中,因为它打算在PHP 6中删除,但该项目被无限期保留,较小的更改在5.3和5.4中着陆)。
最后,函数可以通过引用返回变量(如discussed in the manual here)。这有点繁琐,因为它实际上要求您将&
放在两个位置:在函数声明的开头,说return
应该意味着“返回此变量引用“not”返回此值“;并在调用它的代码中,为该引用分配一个变量,而不是仅仅复制它的值。这是一个愚蠢的例子,它将参考参数与参考回报结合起来(两者不必在一起,这只是一个例子):
function &bar(&$some_param) { return $some_param; }
$a = 1;
$b =& bar($a);
// $b and $a now point at the same variable, not just the same value
// it was passed into and out of a function, and assigned to a new variable,
// but all those operations were by reference
请注意,许多人错误地认为通过引用传递变量会给他们带来性能优势,而这通常是他们使用call-time pass-by-reference的唯一原因。这实际上通常是错误的,因为支持PHP的Zend引擎使用一种称为“写入时复制”的技术来保留多个变量,这些变量碰巧具有指向同一块内存的相同值,即使它们没有被绑定为引用。事实上,由于引擎跟踪哪些变量处于写时复制状态,引用分配通常会击败此优化。
答案 1 :(得分:3)
不,不是。
对象始终自动作为参考传递(信息!请参阅下文以获取更多重要信息!)
声明参数作为参考必须在函数定义中发生:
function test(&$var) {}
调用时不:
// wrong
$var = '123';
test(&$var);
<小时/> 如果像往常一样传递对象,则可以更改对象的状态(属性)。
$obj
是类TestClass
的实例,其中包含名为hello
(click here for a full sample at Ideone.com)的成员变量:
function modify($obj) { $obj->hello = 'world (modified)!'; }
$obj->hello = 'world';
modify($obj);
var_dump($obj->hello); // outputs "world (modified!)"
这应该是不言自明的。现在,使用相同的代码,但为$obj
分配另一个值而不是修改对象的状态不会导致修改(→ Ideone.com):
function modify($obj) { $obj = 42; }
// ...
var_dump($obj->hello); // outputs "world"
仅明确接受参数作为参考使我们能够完全更改变量的内容(→ Ideone.com):
function modify(&$obj) { $obj = 42; }
// ...
var_dump($obj); // outputs "42"
答案 2 :(得分:1)
不,那些不一样。 PHP 5.4+只是在通过检查声明调用函数时检测是否需要引用。
所以不,不要弃用,因为如果这是您的预期用途,您需要在函数声明中使用引用运算符。