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

 个人博客网站文章地址:http://blog.mclink.xyz/index/article/index/id/36.html

 很多新手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('test1');
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 = 'test2';
//比较此时两个对象的$name值
echo "修改后对象1的name值为:".$o1->name."<br/>";
echo "修改后对象2的name值为:".$o2->name."<br/>";

打印结果:

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

那么什么是浅复制呢?

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

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

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

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

何为引用的对象呢?就是说可能类的成员变量存储的是另一个类的实例化对象,我们假设为对象3,那么这样的话,对象1和对象2的成员变量是共用对象3的。

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

两种方法:

①利用__clone魔术方法

public function __clone()
{
    $this->obj = clone $this->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);

打印结果:

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

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

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

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MClink

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值