ホームページ > バックエンド開発 > PHPの問題 > PHPの深いコピーと浅いコピーの違いは何ですか

PHPの深いコピーと浅いコピーの違いは何ですか

WBOY
リリース: 2023-03-15 08:08:01
オリジナル
2825 人が閲覧しました

PHP におけるディープ コピーとシャロー コピーの違い: 1. ディープ コピーは代入時の完全なコピーですが、シャロー コピーは単なる参照代入であり、エイリアスを取得するのと同じです。2. ディープ コピーの場合変更を加えてももう一方には影響しませんが、一方に対する浅いコピーの変更は他方に影響を与えます。

PHPの深いコピーと浅いコピーの違いは何ですか

このチュートリアルの動作環境: Windows10 システム、PHP7.1 バージョン、DELL G3 コンピューター

ディープ コピーとシャロー コピーの違いphp の内容は何です。

まず、ディープ コピーとシャロー コピーについての一般的な理解について話しましょう。

ディープ コピー: 代入中の値は完全にコピーされ、完全なコピーで、それらの 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 サイトの他の関連記事を参照してください。

関連ラベル:
php
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート