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 相关文章推荐
mysql_fetch_assoc和mysql_fetch_row的功能加起来就是mysql_fetch_array
Jan 15 PHP
PHP运行模式的深入理解
Jun 03 PHP
php htmlspecialchars()与shtmlspecialchars()函数的深入分析
Jun 05 PHP
php生成随机密码自定义函数代码(简单快速)
May 10 PHP
浅谈PHP接收POST数据方式
Jun 05 PHP
PHP实现删除字符串中任何字符的函数
Aug 11 PHP
Zend Framework开发入门经典教程
Mar 23 PHP
php上传大文件设置方法
Apr 14 PHP
学习PHP session的传递方式
Jun 15 PHP
php日期操作技巧小结
Jun 25 PHP
php正则表达式基本知识与应用详解【经典教程】
Apr 17 PHP
如何理解PHP核心特性命名空间
May 28 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用户注册页面填写信息完整实例(附源码)
2015/11/17 PHP
在openSUSE42.1下编译安装PHP7 的方法
2015/12/24 PHP
关于 Laravel Redis 多个进程同时取队列问题详解
2017/12/25 PHP
PHP simplexml_load_file()函数讲解
2019/02/03 PHP
PHP实现一个限制实例化次数的类示例
2019/09/16 PHP
自动生成文章摘要的代码[JavaScript 版本]
2007/03/20 Javascript
图片自动缩小 点击放大
2008/07/07 Javascript
Mootools 1.2教程(2) DOM选择器
2009/09/14 Javascript
JavaScript Event学习第七章 事件属性
2010/02/07 Javascript
DIV菜单层实现代码
2010/11/19 Javascript
js获取下拉列表框中的value和text的值示例代码
2014/01/11 Javascript
实现音乐播放器的代码(html5+css3+jquery)
2015/08/04 Javascript
jQuery点击弹出层弹出模态框点击模态框消失代码分享
2017/01/21 Javascript
nodejs 子进程正确的打开方式
2017/07/03 NodeJs
详解使用Typescript开发node.js项目(简单的环境配置)
2017/10/09 Javascript
node打造微信个人号机器人的方法示例
2018/04/26 Javascript
Vue Extends 扩展选项用法完整实例
2019/09/17 Javascript
layui 监听select选择 获取当前select的ID名称方法
2019/09/24 Javascript
Ant Design Vue table中列超长显示...并加提示语的实例
2020/10/31 Javascript
[04:52]第二届DOTA2亚洲邀请赛主赛事第一天比赛集锦:OG娜迦海妖放大配合谜团大中3人
2017/04/02 DOTA
详解Python中的变量及其命名和打印
2016/03/11 Python
Python实现的栈(Stack)
2018/01/26 Python
python搜索包的路径的实现方法
2019/07/19 Python
Python爬虫库requests获取响应内容、响应状态码、响应头
2020/01/25 Python
python能否java成为主流语言吗
2020/06/22 Python
Django xadmin安装及使用详解
2020/10/26 Python
html5自动播放mov格式视频的实例代码
2020/01/14 HTML / CSS
加拿大领先的时尚和体育零售商:Sporting Life
2019/12/15 全球购物
高级技校毕业生自荐信
2013/11/18 职场文书
英语感恩演讲稿
2014/01/14 职场文书
校园奶茶店创业计划书
2014/01/23 职场文书
矿泉水广告词
2014/03/20 职场文书
建设办主任四风问题整改思路和措施
2014/09/20 职场文书
2014年党风建设工作总结
2014/11/19 职场文书
《蟋蟀的住宅》教学反思
2016/02/17 职场文书
导游词之京东大峡谷旅游区
2019/10/29 职场文书