深入理解php的浅复制与深复制

我们经常性赋值给另一个变量,比如说:

class a{

public $pp;

}

//创建一个对象$A;

$A = new a();

$A->pp = "123";

$B = $A;

$B->pp = "456";

同时输出$A,$B的值都是“456“ 充分说明他俩共用一段空间,也就是说$B是$A的一个引用,并没有给B单独开辟一段空间

所以说这是一个浅复制;

我们来看一段深复制

$B = clone $A;

通过关键词我们可以知道是克隆了$A给$B,也就是说给B开辟了单独空间;我们来运行一下,结果如下:

object(a)[1]
  public 'dd' => 

string

 '123' (length=3)
  public 'pp' => null
object(a)[2]
  public 'dd' => 

string

 '123' (length=3)
  public 'pp' => 
 从结果可以看出来 A和B已经完全不是同一个对象了,这就完成了一个深复制;
到这里我们真的可以说完成了一个深复制了吗?NO,如果说我们假设每一个对象都是唯一的,比如说是电脑IP不允许重复,那么我们的深复制会产生两个一样的电脑IP,所以说
这样是不行的,这是后就用到了一个php5的class自带的魔术函数__clone();这个函数帮助我们实现深复制,当我们去clone一个对象的时候就调用了类里面的这个函数,我们可以在这个函数中去
设置我们的唯一不变量,例如以下代码;若我们没有在clone函数中调用这个setapp,那么会产生一摸一样的成员变量$pp,修改过得代码如下:

<?php
class a{
public $dd = "123";
public $pp=null ;
public function setapp(){
$this->pp = new app();
}
public function getapp(){
return app();
}
function __clone(){
$this->setapp();
}

}
class app{
public $vv=null;
}
$A = new a();
$A->setapp();
$B = clone $A;
var_dump($B);
var_dump($A);

这是我在理解clone时候做的一个演示例子:

类app和a是聚合关系,也就说是一种弱关系型的关联,大家猜一下这个输出结果,我这里先贴上运行结果仅供参考:

object(a)[3]
  public 'dd' => 

string

 '123' (length=3)
  public 'pp' => 
    object(app)[4]
      public 'vv' => null
object(a)[1]
  public 'dd' => 

string

 '123' (length=3)
  public 'pp' => 
    object(app)[2]
      public 'vv' => null

我们可以清楚的看出这是一个深复制,因为对象的id都不一样,

到这里我们算知道了真正的深复制,可是我们假如有n多个唯一成员,那么我们要一个一个在clone中进行改变吗?

这个是相对比较麻烦的,所以有一个更加简便的方法,那就是利用输入输出流的方式进行深复制;

利用php的serialize的函数我们先进行序列化,然后unserialize函数进行反序列化,读入读出就完全进行了一次复制, 

这就是最简便的方式进行深复制,代码如下:

<?php
class a{
public $dd = "123";
public $pp=null ;
public function setapp(){
$this->pp = new app();
}
public function getapp(){
return app();
}
function __clone(){
$this->setapp();
}

}
class app{
public $vv=null;
}
$A = new a();
$A->setapp();
$B = unserialize(serialize($A));
var_dump($B);
var_dump($A);

运行结果如下:

object(a)[3]
  public 'dd' => 

string

 '123' (length=3)
  public 'pp' => 
    object(app)[4]
      public 'vv' => null
object(a)[1]
  public 'dd' => 

string

 '123' (length=3)
  public 'pp' => 
    object(app)[2]
      public 'vv' => null
我们从结果可以看出不论是对象本体还是成员变量都是完全不同的东西;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值