PHP中深拷貝和淺拷貝的區別:1、深拷貝賦值時是完全複製,而淺拷貝只是參照賦值,相當於取了一個別名;2、深拷貝若對其中一個做出改變不會影響另一個,而淺拷貝對其中一個進行修改會影響另一個。
本教學操作環境:windows10系統、PHP7.1版、DELL G3電腦
先說一下深拷貝和淺拷貝通俗理解
深拷貝:賦值時值完全複製,完全的copy,對其中一個作出改變,不會影響另一個
淺拷貝:賦值時,參照賦值,相當於取了一個別名。對其中一個修改,會影響另一個
PHP中, = 賦值時,普通物件是深拷貝,但對物件來說,是淺拷貝。也就是說,物件的賦值是參照賦值。(物件作為引數傳遞時,也是參照傳遞,無論函數定義時引數前面是否有&符號)
php4中,物件的 = 賦值是實現一份副本,這樣存在很多問題,在不知不覺中我們可能會拷貝很多份副本。
php5中,物件的 = 賦值和傳遞都是參照。要想實現拷貝副本,php提供了clone函數實現。
clone完全copy了一份副本。但是clone時,我們可能不希望copy源物件的所有內容,那我們可以利用__clone來操作。
在__clone()中,我們可以進行一些操作。注意,這些操作,也就是__clone函數是作用於拷貝的副本物件上的
<?php //普通物件賦值,深拷貝,完全值複製 $m = 1; $n = $m; $n = 2; echo $m;//值複製,對新物件的改變不會對m作出改變,輸出 1.深拷貝 echo PHP_EOL; /*==================*/ //物件賦值,淺拷貝,參照賦值 class Test{ public $a=1; } $m = new Test(); $n = $m;//參照賦值 $m->a = 2;//修改m,n也隨之改變 echo $n->a;//輸出2,淺拷貝 echo PHP_EOL; ?>
由於物件的賦值時參照,要想實現值複製,php提供了clone函數來實現複製物件。
但是clone函數存在這麼一個問題,克隆物件時,原物件的普通屬效能值複製,但是源物件的物件屬性賦值時還是參照賦值,淺拷貝。
<?php class Test{ public $a=1; } class TestOne{ public $b=1; public $obj; //包含了一個物件屬性,clone時,它會是淺拷貝 public function __construct(){ $this->obj = new Test(); } } $m = new TestOne(); $n = $m;//這是完全的淺拷貝,無論普通屬性還是物件屬性 $p = clone $m; //普通屬性實現了深拷貝,改變普通屬性b,不會對源物件有影響 $p->b = 2; echo $m->b;//輸出原來的1 echo PHP_EOL; //物件屬性是淺拷貝,改變物件屬性中的a,源物件m中的物件屬性中a也改變 $p->obj->a = 3; echo $m->obj->a;//輸出3,隨新物件改變 ?>
要想實現物件真正的深拷貝,有下面兩種方法:
寫clone函數:如下
<?php class Test{ public $a=1; } class TestOne{ public $b=1; public $obj; //包含了一個物件屬性,clone時,它會是淺拷貝 public function __construct(){ $this->obj = new Test(); } //方法一:重寫clone函數 public function __clone(){ $this->obj = clone $this->obj; } } $m = new TestOne(); $n = clone $m; $n->b = 2; echo $m->b;//輸出原來的1 echo PHP_EOL; //可以看到,普通屬性實現了深拷貝,改變普通屬性b,不會對源物件有影響 //由於改寫了clone函數,現在物件屬性也實現了真正的深拷貝,對新物件的改變,不會影響源物件 $n->obj->a = 3; echo $m->obj->a;//輸出1,不隨新物件改變,還是保持了原來的屬性 ?>
改寫__clone()函數不太方便,而且你得在每個類中把這個類裡面的物件屬性都在__clone()中 一一 clone
第二種方法,利用序列化反序列化實現,這種方法實現物件的深拷貝簡單,不需要修改類
<?php class Test{ public $a=1; } class TestOne{ public $b=1; public $obj; //包含了一個物件屬性,clone時,它會是淺拷貝 public function __construct(){ $this->obj = new Test(); } } $m = new TestOne(); //方法二,序列化反序列化實現物件深拷貝 $n = serialize($m); $n = unserialize($n); $n->b = 2; echo $m->b;//輸出原來的1 echo PHP_EOL; //可以看到,普通屬性實現了深拷貝,改變普通屬性b,不會對源物件有影響 $n->obj->a = 3; echo $m->obj->a;//輸出1,不隨新物件改變,還是保持了原來的屬性,可以看到,序列化和反序列化可以實現物件的深拷貝 ?>
還有第三種方法,其實和第二種類似,json_encode之後再json_decode,實現賦值
推薦學習:《》
以上就是php中深拷貝和淺拷貝的區別是什麼的詳細內容,更多請關注TW511.COM其它相關文章!