PHP中的浅复制与深复制的实例详解


Posted in PHP onOctober 26, 2017

PHP中的浅复制与深复制的实例详解

前言:

最近温习了一下Design Pattern方面的知识,在看到Prototype Pattern这一设计模式时,注意到其中涉及到一个浅复制与深复制的问题。这里来总结一下,提醒自己以后一定要多加注意。

自PHP5起,new运算符自动返回一个引用,一个 对象变量 已经不再保存整个对象的值,只是保存一个标识符来访问真正的对象内容。当对象作为参数传递,作为结果返回,或者赋值给另外一个变量,另外一个变量跟原来的不是引用的关系,只是他们都保存着同一个标识符的拷贝,这个标识符指向同一个对象的真正内容。

这里举个栗子:

class Example1
{
  public $name;

  public function __construct($name)
  {
    $this->name = $name;
  }
}

$ex1 = new Example('test1');// $ex1->name现在是:test1
$ex2 = $ex1;// $ex2->name现在是:test1

$ex2->name = 'test2';// 这样修改一下之后,$ex1->name与$ex2->name都变为了:test2

通过上面这个例子,应该可以理解对象间引用的概念了,那么我们继续往下走,在php中提供了 clone 这个关键字来进行对象复制,还是用上面的类来演示一下:

$ex1 = new Example('test1');// $ex1->name现在是:test1
$ex2 = clone $ex1;//$ex2->name现在是:test1

$ex2->name = 'test2';//现在$ex1->name还是test1,而$ex2->name是test2

这里看到,通过clone之后,$ex1与$ex2是两个不同的对象,他们拥有各自的变量环境。但是这里需要注意,在这两个对象内部,拥有的是值类型的数据,如果是内部拥有的是引用类型,那么通过clone得到的新对象中的引用则仍然指向原引用。这里就引申出 浅复制 与 深复制 的概念:

浅复制: 使用clone来复制对象,这种复制叫做“浅复制“,被赋值对象的所有变量都还有与原来对象相同的值,而所有的对其他对象的引用都仍然指向原来的对象。

深复制:被复制的对象的所有的变量都含有与原来的对象相同的值,除去那些引用其他对象的变量。

默认使用 clone 是进行一个浅复制,那么如何才能进行深复制呢?

方式一:利用__clone方法

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

这种方式非常直观,但是却有一个很麻烦的操作方式,就是当类中包含多个引用时,你就需要在__clone方法中逐个重新设置。而且还要处理一些循环引用的问题。是很复杂的。

方式二:利用串行化(冷藏与解冻)

$tmp = serialize($ex1);
$ex2 = unserialize($tmp);

这时候得到的$ex2就是一个全新的对象,这个过程在java中也叫作”冷藏“与”解冻“过程。

序列化是一个递归的过程,我们不需要理会被对象内部引用了多少个对象以及引用了多少层对象,我们都可以彻底的复制。方式二真的很黄很暴力,但是我很喜欢。

如有疑问请留言或者到本站社区交流讨论,感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

PHP 相关文章推荐
PHP中防止SQL注入攻击和XSS攻击的两个简单方法
Apr 15 PHP
PHP中调用ASP.NET的WebService的代码
Apr 22 PHP
PHP下通过exec获得计算机的唯一标识[CPU,网卡 MAC地址]
Jun 09 PHP
基于PHP静态类的原罪详解
May 06 PHP
PHP输出XML到页面的3种方法详解
Jun 06 PHP
php生成数组的使用示例 php全组合算法
Jan 16 PHP
PHP会话控制:Session与Cookie详解
Sep 27 PHP
Zend Framework动作助手Redirector用法实例详解
Mar 05 PHP
php中mkdir()函数的权限问题分析
Sep 24 PHP
php 解析xml 的四种方法详细介绍
Oct 26 PHP
Laravel向公共模板赋值方法总结
Jun 25 PHP
php设计模式之单例模式用法经典示例分析
Sep 20 PHP
thinkPHP5实现数据库添加内容的方法
Oct 25 #PHP
thinkPHP5分页功能实现方法分析
Oct 25 #PHP
thinkPHP框架中执行原生SQL语句的方法
Oct 25 #PHP
php调用云片网接口发送短信的实现方法
Oct 25 #PHP
OAuth认证协议中的HMACSHA1加密算法(实例)
Oct 25 #PHP
Laravel学习教程之request validation的编写
Oct 25 #PHP
Yii2框架实现登录、退出及自动登录功能的方法详解
Oct 24 #PHP
You might like
php 将字符串按大写字母分隔成字符串数组
2010/04/30 PHP
用PHP解决的一个栈的面试题
2014/07/02 PHP
php学习笔记之基础知识
2014/11/08 PHP
php使用数组填充下拉列表框的方法
2015/03/31 PHP
PHP编程开发怎么提高编程效率 提高PHP编程技术
2015/11/09 PHP
Thinkphp框架+Layui实现图片/文件上传功能分析
2020/02/07 PHP
Laravel实现批量更新多条数据
2020/04/06 PHP
JS动画效果代码3
2008/04/03 Javascript
jquery中dom操作和事件的实例学习 仿yahoo邮箱登录框的提示效果
2011/11/30 Javascript
表单提交前触发函数返回true表单才会提交
2014/03/11 Javascript
jQuery实现返回顶部功能适合不支持js的浏览器
2014/08/19 Javascript
javascript制作坦克大战全纪录(2)
2014/11/27 Javascript
jquery中animate的stop()方法作用实例分析
2015/01/30 Javascript
javascript显式类型转换实例分析
2015/04/25 Javascript
jQuery实现HTML表格单元格的合并功能
2016/04/06 Javascript
Javascript数组中push方法用法分析
2016/10/31 Javascript
AngularJS实现页面定时刷新
2017/03/14 Javascript
JS实现线性表的链式表示方法示例【经典数据结构】
2017/04/11 Javascript
vue+php实现的微博留言功能示例
2019/03/16 Javascript
JavaScript canvas绘制渐变颜色的矩形
2020/02/18 Javascript
vue中利用three.js实现全景图的完整示例
2020/12/07 Vue.js
Python中的True,False条件判断实例分析
2015/01/12 Python
Python编程之gui程序实现简单文件浏览器代码
2017/12/08 Python
使用django-guardian实现django-admin的行级权限控制的方法
2018/10/30 Python
基于python检查矩阵计算结果
2020/05/21 Python
pytorch 实现L2和L1正则化regularization的操作
2021/03/03 Python
欧洲第一中国智能手机和平板电脑网上商店:CECT-SHOP
2018/01/08 全球购物
澳大利亚领先的美容护肤品零售商之一:SkincareStore
2018/01/22 全球购物
数据库专业英语
2012/11/30 面试题
残疾人创业典型事迹
2014/02/01 职场文书
建设投标担保书
2014/05/13 职场文书
简历自我评价模板
2015/03/11 职场文书
刑事起诉书范文
2015/05/19 职场文书
信用卡工资证明范本
2015/06/19 职场文书
2015年中学图书馆工作总结
2015/07/22 职场文书
小学生优秀作文范文(六篇)
2019/07/10 职场文书