PHP におけるディープ コピーとシャロー コピーの違い: 1. ディープ コピーは代入時の完全なコピーですが、シャロー コピーは単なる参照代入であり、エイリアスを取得するのと同じです。2. ディープ コピーの場合変更を加えてももう一方には影響しませんが、一方に対する浅いコピーの変更は他方に影響を与えます。
このチュートリアルの動作環境: Windows10 システム、PHP7.1 バージョン、DELL G3 コンピューター
まず、ディープ コピーとシャロー コピーについての一般的な理解について話しましょう。
ディープ コピー: 代入中の値は完全にコピーされ、完全なコピーで、それらの 1 つに変更を加えると、他のものには影響を与えません
浅いコピー: 代入する場合、参照代入はエイリアスを取得することと同じです。どちらか一方を変更すると、もう一方にも影響します。
PHP では、= を指定すると、通常のオブジェクトは深いコピーになりますが、オブジェクトの場合は浅いコピーになります。言い換えれば、オブジェクトの割り当ては参照割り当てです。 (オブジェクトがパラメータとして渡される場合、関数の定義時にパラメータの前にアンパサンドがあるかどうかに関係なく、参照によっても渡されます)
php4 では、オブジェクトの = 割り当てコピーを実装することですが、これには多くの問題があり、多数のコピーを作成する可能性があります。
PHP5 では、オブジェクトの = 代入と転送は両方とも参照です。コピーを実装するために、PHP にはクローン関数の実装が用意されています。
clone は完全なコピーを作成します。ただし、クローンを作成する場合、ソース オブジェクトのすべての内容をコピーしたくない場合は、__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 関数が提供されています。
しかし、クローン関数には問題があります。オブジェクトがクローンされるとき、元のオブジェクトの通常の属性は値によってコピーできますが、ソース オブジェクトのオブジェクト属性が割り当てられるときは、それらはそのまま残ります。参照割り当てと浅いコピー。
<?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,随新对象改变 ?>
オブジェクトの真のディープ コピーを実現するには、2 つの方法があります:
クローン関数を次のように記述します:
<?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
2 番目の方法は、シリアル化と逆シリアル化を使用することです。この方法はオブジェクトを実現します。ディープコピーは簡単です。クラスを変更する必要はありません
<?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,不随新对象改变,还是保持了原来的属性,可以看到,序列化和反序列化可以实现对象的深拷贝 ?>
3 番目の方法もありますが、これは実際には 2 番目の方法に似ています。json_encode、次に json_decode を使用して割り当てを実現します
推奨学習: "PHP ビデオ チュートリアル >>
以上がPHPの深いコピーと浅いコピーの違いは何ですかの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。