PHP中的对象复制与克隆

时间:2011-08-07 12:37:01

标签: php object clone

请考虑以下事项:

$object1 = new stdClass();
$object2 = $object1;
$object3 = clone $object1;

$object1->content = 'Ciao';

var_dump($object1);
 // Outputs object(stdClass)#1 (1) { ["content"]=> string(4) "Ciao" }
var_dump($object2);
 // Outputs object(stdClass)#1 (1) { ["content"]=> string(4) "Ciao" }
var_dump($object3);
 // Outputs object(stdClass)#2 (0) { }

$object2的内容是否与$object1相同,这是正常的PHP行为吗?

对我来说,$object2听起来像$object1而不是副本。 在更改内容之前克隆对象确实就像一个副本。 这种行为与变量的行为不同,对我来说似乎不直观。

4 个答案:

答案 0 :(得分:39)

是的,这是正常的。在PHP5中,对象始终“已分配”。要实际制作对象的副本,您需要clone它。

为了更正确,让我引用the manual

  

从PHP5开始,对象变量不再包含对象本身作为值。它只包含一个对象标识符,允许对象访问者查找实际对象。当一个对象通过参数发送,返回或分配给另一个变量时,不同的变量不是别名:它们包含标识符的副本,它指向同一个对象。

答案 1 :(得分:13)

这是正常的,我不会认为这不直观(对象实例):

$object1 = new stdClass();

将新对象实例分配给$object1

$object2 = $object1;

将对象实例分配给$object2

$object3 = clone $object1;

将从现有对象实例克隆的新对象实例分配给$object3

如果不是这样,每次需要传递具体对象实例时,都需要通过引用传递它。至少这是繁琐的,但PHP在版本4中这样做(比较zend.ze1_compatibility_mode core )。那没用。

Cloning allows the object to specify how it get's copied

答案 2 :(得分:9)

对象副本与对象克隆

class test{
public $name;
public $addr;
}
// i create a object $ob
$ob=new test();

// object copy 

$ob2=$ob;

// in object copy both object will represent same memory address 
// example 
$ob->name='pankaj raghuwanshi';

// i am printing second object
echo $ob2->name;
// output is : pankaj raghuwanshi

// another example 

$ob2->name='raghuwanshi pankaj';
echo $ob->name;
// output is :  raghuwanshi pankaj

// it means in copy of object original and copy object share same memory place

现在克隆一个对象

$ob1=clone $ob;

echo $ob1->name;  // output is :  raghuwanshi pankaj
echo $ob->name;   // output is :  raghuwanshi pankaj

 $ob1->name='PHP Clone';
 $ob->name='PHP Obj';

echo $ob1->name;  // output is :  PHP Clone
echo $ob->name;   // output is :  PHP Obj

// on the base of these output we can say both object have their own memory space 
// both are independent 

答案 3 :(得分:4)

php5中的对象本质上是指针,也就是说,对象变量只包含位于其他位置的对象数据的地址。作业$obj1 = $obj2仅复制此地址,并且不会触及数据本身。这可能确实看似违反直觉,但实际上它非常实用,因为您很少需要拥有该对象的两个副本。我希望php数组使用相同的语义。