最后我有话要问社区
我的例子是:我有一些带有内部数组的类似盒子的对象,我希望在方法中操作这些数组,但在合并操作后,捐赠盒子必须为空。我目前使用引用是为了不复制大数组,但我最近刚刚看到一篇很棒的帖子:不要使用php引用。
class Box implements MadeUpArrayLikeInterfaces {
protected $v = array();
...
public function __clone() {
foreach ($this->v as &$v) {// correct the mess left behind the cloning process?
if (is_object($v)) $v = clone $v;// perhaps I shouldn't deep clone anything?
}
}
public function merge() {
$boxes = func_get_args();// variable argument list
arary_unshift($boxes,$this->v);
array_walk(array($this,'walkUnwrap'),$boxes);// prepare input, allow only arrays
$this->v = call_user_func('array_merge',array_filter($boxes));// merge
}
public function import(self $box) {// edited to make more sense
$this->v = array_merge($this->v,$box->v);// do the merge
$box->v = array();
}
public function export() {
$e = array(); // empty array that may be referenced
$r =& $this->v; // avoid copying for return
$this->v =& $e; // point to empty because assignment would erase $r as well
return $r; // return contents
}
private static function walkUnwrap(&$v) {// walks on argument list
if ($v instanceof self && $v->v) {// if element is Box, export it
$e = array();
$o = $v; // save reference to the Box
$v =& $v->v;// pass the data
$o->v =& $e;// this box should now be empty
} elseif (!is_array($v)) $v = null;// if it's anything but array get rid of it
}
}
所以现在我想知道我的方法是否真的正确。这些操作是否按照帖子中的规定"书写",因此最好使用参考资料?这些是复制值吗?
谢谢大家
edited:事实上,我很粗心,导入函数要简单得多,我有一个更好的函数,它还使用了一些引用,这些引用可能有助于显示
否,如果将$box->v =& $e;
赋值,则如果随后将$box->v
更改为array('foo', 'bar')
,则变量$e
也将更改为该值。因此,下次在类方法import()
中分配$e
时,参数$box
的属性v
也将为array('foo', 'bar')
。
如果您能够确保$box->v
在$box->v =& $e;
代码行之后的任何地方都不会被更改,那么它就可以工作了。但对我来说似乎有点懒惰和冒险。
由于PHP5,大部分内容都被视为参考。这意味着或多或少每个复杂类型的变量(objects
)都只通过引用传递(对于函数/方法调用)。
要创建一个具有相同内容的新实例("复杂"变量的副本),请使用语言构造clone
。
但并不是每个对象都是可克隆的。您可以使用魔术方法__clone()
拒绝克隆自己类的对象。
例如,singleton类通常是不可克隆的(这是有道理的)。所以单例只能通过引用传递,因为它只能存在一次。