Rumah  >  Artikel  >  pembangunan bahagian belakang  >  如何理解PHP中的对象引用,浅复制以及深复制

如何理解PHP中的对象引用,浅复制以及深复制

不言
不言asal
2018-04-09 17:06:541445semak imbas

 本篇文章给大家分享的内容是关于如何理解PHP中的对象引用,浅复制以及深复制 ,有需要的朋友可以参考一下

 很多新手PHPer对oop编程不熟的容易对这些概念忽视,最近在读初级PHP工程师这本书的时候对对象引用这一部分比较模糊,查了一些资料,理解了一下,想在此做一下记录,告诉自己这些基础一定要巩固好。

参考文章:https://blog.csdn.net/hel12he/article/details/49617023

                  https://blog.csdn.net/koastal/article/details/52163483

首先我们应该先明白PHP中内存空间是如何分布的。一般来说,内存空间分为堆内存,栈内存,数据段,代码段,如下图:

那么什么是对象的引用呢?

   当我们使用new关键字对某个类进行实例化的时候,我们可以通过这个对象来访问该类中的属性以及方法。并且每个对象之间都是独立的,例如一个汽车类有着大小,颜色等属性,有行驶的方法,这个类可以被实例化成多个对象,每个对象的属性方法都可以修改,也就是说对象是有自己的内存空间的,它里面包含了实例该类的属性以及方法,对对象进行引用,或者说是使用别名,实际上指向的是同一个内存空间,例如:

<?php
  class One
{
    public $name;

    public function __construct($name)
    {
        $this->name = $name;
    }
}
//实例化,并且向构造函数传递参数
$o1 = new One(&#39;test1&#39;);
echo "对象1的name值为:".$o1->name."<br/>";
//引用
$o2 = $o1;
//打印对象2的$name属性
echo "对象2的name值为:".$o2->name."<br/>";
//修改对象$o2的$name属性
echo "修改对象2的name为test2"."<br/>";
$o2->name = &#39;test2&#39;;
//比较此时两个对象的$name值
echo "修改后对象1的name值为:".$o1->name."<br/>";
echo "修改后对象2的name值为:".$o2->name."<br/>";

打印结果:

由此可知,引用本质上只是只是对象的别名而已,实际上被引用对象和引用对象指向的内存空间还是一样的。(这里$o2=&o1的效果也是一样的)。


那么什么是浅复制呢?

概念:使用clone来复制对象,这种复制叫做“浅复制“,被赋值对象的所有变量都还有与原来对象相同的值,而所有的对其他对象的引用都仍然指向原来的对象。也就是说,浅复制仅仅复制所考虑的对象,而不复制它所引用的对象。

我们使用相同的例子,把$o2=$o1改成$o2=clone $o1.看看会发生什么。打印结果如下图:


可以看到,当我们只修改对象2的值的时候,对象1的并没有发生改变,因为使用clone关键字是生成了一个对象的副本,这个副本也是有自己的内存空间的,它们之前相互独立。但是浅复制中是没有把它所引用的对象也复制下来。


前面说的东西都是内容只有数值的情况,当内容中也有引用的对象那就不一样了,也就引出了深复制的概念。

深复制概念:被复制的对象的所有的变量都含有与原来的对象相同的值,除去那些引用其他对象的变量。也就是说深复制把要复制的对象所引用的对象都复制了一遍。

两种方法:

利用__clone魔术方法

public function __clone()
{
    $this->obj = new Obj();
}


利用串行化

$t = serialize($o1);
$o2 = unserialize($t);


举个栗子:

<?php
header("Content-type:text/html;charset=utf-8");
class TvControl{
}
class Tv{
    private $color;
    private $tvControl;
    function __construct(){
        $this->color = "black";
        $this->tvControl = new TvControl();
    }
    
    function getTvControl(){
        return $this->tvControl;
    }
}
		$tv1 = new Tv();
		$tvControl1 = $tv1->getTvControl();
		echo "原始类:"."<br/>";
		var_dump($tv1);
		echo "<br/>";
		$tv2 = $tv1;
		echo "引用类:"."<br/>";
		var_dump($tv2);
		echo "<br/>";
		$tv3 = clone $tv1;
		echo "克隆(浅复制):"."<br/>";
		var_dump($tv3);
		echo "<br/>";
		$tv4 = unserialize(serialize($tv1));
		echo "深复制:"."<br/>";
		var_dump($tv4);

打印结果:


深复制获取到的对象也是一个全新的对象。

那么如何比较两个对象是否引用于同一个对象呢?

我么可以使用“===”来进行比较两个对象是否引用于同一个初始对象。而“==”只能比较两个对象是否具有相同的类和属性。

相关推荐:

深入理解PHP数组的count函数

深度理解php循环语句


Atas ialah kandungan terperinci 如何理解PHP中的对象引用,浅复制以及深复制 . Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn