注意:这个答案是对最初提出的问题的回答。新问题有些不同,尽管在这种情况下使用对象不会改变基本行为。
PHP 引用不能被“链接”——=&
操作符不像指针引用/取消引用机制,它将两个(或更多)变量绑定在一起。但重要的是,两个变量名都不比另一个更“真实”——它们都是(或全部)对无名值的引用。
例如,$foo =& $bar
获取指向的值$bar
,也指向$foo
该值。如果您随后分配给任一变量(例如$foo = 42;
或$bar = 42;
),则该值将被更新。一些动作,例如unset($bar)
作用于变量,而不是值,所以它们只影响那个特定的变量,而不是引用的值。
您可以通过运行以下命令来查看实际情况:$foo = 42; $bar =& $foo; unset($foo); echo $bar;
请注意,这$foo
是该值的“原始”名称,但即使未设置,该值仍然存在。然后,您可以将变量重$foo
用于完全不同的值,而不会受到$bar
任何影响。
如果您获取一个已经是引用的变量,并将其作为对其他内容的引用,这就像取消设置引用并重用变量名来设置一个新的。因此该值不受影响,并且先前引用的变量名称变得独立。
在您的代码中,您可以这样做:
// 1: Make $values['a'] point to the value currently pointed at by $values['b']
$values['a'] =& $values['b'];
// 2: Make $values['b'] point to the value currently pointed at by $values['c']
// the previous value is now only pointed to by $values['a']
$values['b'] =& $values['c'];
// 3: Set the value shared by $values['b'] and $values['c'] to 1
$values['c'] = 1;
(作为技术细节,我在这里所说的“值”是 PHP 内部结构中的一个结构,称为zval
.)
编辑更新的问题:
对象似乎使这更复杂,因为它们具有额外的间接级别,其工作方式几乎相同:$foo = new A('a'); $bar = $foo;
仍然创建两个值(zval
s),但这些值都是指向同一个对象的指针。
在您的情况下,这没有什么区别,因为您仍在使用引用分配 ( =&
) - 如果没有,您将得到相同的结果:
// 1: Make the value of $values['a'] point to the object currently pointed at by the value of $values['b']
$values['a'] = $values['b'];
// 2: Make the value of $values['b'] point to the object currently pointed at by the value of $values['c']
// the previous object is now only pointed to by the value of $values['a']
$values['b'] = $values['c'];
我们现在可以更改三件事:变量、它指向的值和指向的对象:
// Change the object: updates the object shared by $values['b'] and $values['c']
$values['c']->value = 42;
// Change the value: will only update $values['b'] if =& was used to tie them together
$values['c'] = 42;
// Change the variable: will never affect $values['b']
unset($values['c']);