对象的复制

3.4.2.4 对象的复制

PHP中普通变量的复制可以通过直接赋值完成,比如:

$a = array();
$b = $a;

但是对象无法这么进行复制,仅仅通过赋值传递对象,它们指向的都是同一个对象,修改时也不会发生硬拷贝。比如上面这个例子,我们把$a赋值给$b,然后如果我们修改$b的内容,那么这时候会进行value分离,$a的内容是不变的,但是如果是把一个对象赋值给了另一个变量,这俩对象不管哪一个修改另外一个都随之改变。

class my_class
{
    public $arr = array();
}

$a = new my_class;
$b = $a;

$b->arr[] = 1;

var_dump($a === $b);
====================
输出:bool(true)

还记得我们在《2.1.3.2 写时复制》一节讲过zval有个类型掩码: __type_flag 吗?其中有个是否可复制的标识:IS_TYPE_COPYABLE__ ,copyable的意思是当value发生duplication时是否需要或能够copy,而object的类型是不能复制(不清楚的可以翻下前面的章节),所以我们不能简单的通过赋值语句进行对象的复制。

PHP提供了另外一个关键词来实现对象的复制:clone

$copy_of_object = clone $object;

clone出的对象就与原来的对象完全隔离了,各自修改都不会相互影响,另外如果类中定义了__clone()魔术方法,那么在clone时将调用此函数。

clone的实现比较简单,通过zend_object.clone_obj(即:zend_objects_clone_obj())完成。

//zend_objects.c
ZEND_API zend_object *zend_objects_clone_obj(zval *zobject)
{
    zend_object *old_object;
    zend_object *new_object;

    old_object = Z_OBJ_P(zobject);
    //重新分配一个zend_object
    new_object = zend_objects_new(old_object->ce);

    //浅复制properties_table、properties
    //如果定义了__clone()则调用此方法
    zend_objects_clone_members(new_object, old_object);

    return new_object;
}
联系我们

邮箱 626512443@qq.com
电话 18611320371(微信)
QQ群 235681453

Copyright © 2015-2024

备案号:京ICP备15003423号-3