2011-08-07 151 views
25

考慮以下幾點:對象複製與克隆在PHP

$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而不是副本。 更改內容之前克隆對象的行爲就像一個副本。 這種行爲與變量發生的行爲不同,對我來說似乎很不直觀。

+1

的這只是從缺少規範導致的另一個PHP-WTF。 –

+0

請參閱此處的示例:http://www.php.net/manual/en/language.oop5.references.php。 –

+2

你能否詳細說一下爲什麼這對你來說不直觀? – hakre

回答

38

是的,這是正常的。對象是總是「在PHP5中通過引用」分配「。要實際製作一個對象的副本,您需要clone它。

更正確不過,請允許我引用the manual

隨着PHP5中,一個對象變量不包含對象本身的價值了。它只包含一個對象標識符,它允許對象訪問器找到實際的對象。當一個對象被參數發送,返回或分配給另一個變量時,不同的變量不是別名:它們包含指向同一對象的標識符的副本。

4

php5中的對象基本上是指針,也就是說,對象變量只包含位於其他位置的對象數據的地址。分配$obj1 = $obj2只複製該地址並且不接觸數據本身。這確實可能看起來違反直覺,但實際上它很實用,因爲你很少需要擁有兩個對象副本。我希望php數組使用相同的語義。

+0

使用'ArrayObject' – KingCrunch

+0

當然一些函數只接受本地數組。 '$ result = new ArrayObject(array_map($ cb,$ arrOb-> getArrayCopy()));' – KingCrunch

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

+0

@stereofrog:從面向對象的角度來看,事實並非如此。但是,PHP *實際上也會複製副本,即對象標識符的副本。對象值只有在PHP 5以後纔可以使用標識符,所以實際上,即使對於「我期望副本」,這也很直觀:您將獲得對象標識符的副本。但是,關鍵點可能是理解OO在PHP中的實現方式。 – hakre

+0

@stereofrog:當對象每次在某處傳遞時都要克隆它自己時,會更令人困惑。當他走過一扇門時,你也不會看到一隻狗分裂成兩個相同的副本(而其中一隻狗總是停留在外面......)。另一方面,當我給某人一個我的電話號碼(一個值/原始類型)並且他寫下來時,他只有一個它的副本,而不是數字本身。它無法比較原始類型和對象之間的行爲。 – KingCrunch

+0

@stereofrog:*爲什麼?*是正確的問題。爲了更好地說出原因,OP應該分享一些關於他不直觀的東西。否則很難回答。除此之外,就語言而言,分配和複製(寫入時)可能不同。這可能會讓人聯想到語言是如何工作的,並促進人們理解使用語言作爲工具,而不是對它置之不理。 – hakre

7

對象副本VS對象克隆

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 
+0

這個答案適合現場示例 – PankajR