Копирование объекта по сравнению с клоном в PHP - PullRequest
27 голосов
/ 07 августа 2011

Рассмотрим следующее:

$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) { }

Это нормальное поведение PHP, что $object2 имеет содержимое, идентичное $object1?

Для меня это звучит как $object2ссылка на $object1 вместо копии.Клонирование объекта перед изменением содержимого действует как копия.Это поведение отличается от того, что происходит с переменными, и кажется мне неинтуитивным.

Ответы [ 4 ]

39 голосов
/ 07 августа 2011

Да, это нормально.Объекты всегда «назначаются» по ссылке в PHP5.Чтобы на самом деле сделать копию объекта, вам нужно clone.

Чтобы быть более точным, позвольте мне процитировать руководство :

Начиная с PHP5, переменная объекта больше не содержит сам объект в качестве значения.Он содержит только идентификатор объекта, который позволяет методам доступа к объекту найти фактический объект.Когда объект отправляется с помощью аргумента, возвращается или присваивается другой переменной, различные переменные не являются псевдонимами: они содержат копию идентификатора, который указывает на тот же объект.

13 голосов
/ 07 августа 2011

Это нормально, и я не буду считать это неинтуитивным (для экземпляров объекта):

$object1 = new stdClass();

Назначает новый экземпляр объекта $object1.

$object2 = $object1;

Назначает объектэкземпляр $object2.

$object3 = clone $object1;

Назначает новый экземпляр объекта, клонированный из существующего экземпляра объекта, на $object3.

Если это не так, каждый раз, когда вам нужнопередать конкретный экземпляр объекта, вам нужно будет передать его по ссылке.По крайней мере, это обременительно, но PHP сделал это в версии 4 (сравните zend.ze1_compatibility_mode core ).Это было бесполезно.

Клонирование позволяет объекту указать, как он копируется .

9 голосов
/ 25 июля 2014

копия объекта против клона объекта

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 
4 голосов
/ 07 августа 2011

Объекты в php5 по сути являются указателями, то есть переменная объекта содержит только адрес данных объекта, расположенных где-то еще.Присвоение $obj1 = $obj2 только копирует этот адрес и не касается самих данных.Это действительно может показаться нелогичным, но на самом деле это довольно практично, потому что вам редко нужно иметь две копии объекта.Я бы хотел, чтобы в php-массивах использовалась та же семантика.

...