0

0

【PHP】对象的复制(拷贝)与__clone()方法

php中文网

php中文网

发布时间:2016-09-01 00:00:45

|

1608人浏览过

|

来源于php中文网

原创

参考链接:

1、php.net官网文档 - 对象复制

 

立即学习PHP免费学习笔记(深入)”;

什么时候用到?摘自php.net:

在多数情况下,我们并不需要完全复制一个对象来获得其中属性。但有一个情况下确实需要:如果你有一个 GTK 窗口对象,该对象持有窗口相关的资源。你可能会想复制一个新的窗口,保持所有属性与原来的窗口相同,但必须是一个新的对象(因为如果不是新的对象,那么一个窗口中的改变就会影响到另一个窗口)。还有一种情况:如果对象 A 中保存着对象 B 的引用,当你复制对象 A 时,你想其中使用的对象不再是对象 B 而是 B 的一个副本,那么你必须得到对象 A 的一个副本。

 

立即学习PHP免费学习笔记(深入)”;

尝试使用最简单的“=”

首先要明确的是:php的对象是以一个标识符来存储的,所以对对象的直接“赋值”行为相当于“传引用”

";
}

class A{
    private $a;
    protected $b;
    public $c;

    public function d(){
        echo "A -> d";
    }
}

$a1 = new A();
$a2 = $a1;
$a3 = new A();
dump($a1);
dump($a2);
dump($a3);

 

立即学习PHP免费学习笔记(深入)”;

输出的结果是:

object(A)#1 (3) { ["a":"A":private]=> NULL ["b":protected]=> NULL ["c"]=> NULL } 
object(A)#1 (3) { ["a":"A":private]=> NULL ["b":protected]=> NULL ["c"]=> NULL } 
object(A)#2 (3) { ["a":"A":private]=> NULL ["b":protected]=> NULL ["c"]=> NULL } 

其中可以注意到,作为对象标识符的#n,显示$a1和$a2其实是指向同一个对象,而$a3是另一个对象

所以,如果需要拷贝一个相同且全新的对象,不能直接通过=来复制,否则改变了$a1->a就相当于修改了$a2->a。

 

立即学习PHP免费学习笔记(深入)”;

浅拷贝

PHP5中,类中有个魔术方法__clone(),在配合clone关键字和对象使用的时候,会自动调用(如果没有显式定义,则调用空的方法)。

clone关键字的作用是,复制某一个对象形成一个对象的“浅拷贝”,然后赋值给新的对象,此时对象标识符不同了!

PHP5学习对象教程
PHP5学习对象教程

PHP5学习对象教程由美国人古曼兹、贝肯、瑞桑斯编著,简张桂翻译,电子工业出版社于2007年12月1日出版的关于PHP5应用程序的技术类图书。该书全面介绍了PHP 5中的新功能、编程方法及设计模式,还分析阐述了PHP 5中新的数据库连接处理、错误处理和XML处理等机制,帮助读者系统了解、熟练掌握和高效应用PHP。

下载
";
}

class B{
    public $d;
}

class A{
    public $a;
    public $b;

    public function d(){
        echo "A -> d";
    }
}

$a1 = new A();
$a1->a = 123;
// 这里对象属性的值是一个对象示例,其实就是存储了对象标识符。使用clone关键字生成的拷贝中的b属性仍然指向旧对象的b属性指向的对象,这是"浅拷贝"出现的问题。如果需要指向一个新的对象,必须"深拷贝"
$a1->b = new B();

// PHP 5 only
$a2 = clone $a1;

dump($a1);
dump($a2);

 

立即学习PHP免费学习笔记(深入)”;

输出的结果是:

object(A)#1 (2) { ["a"]=> int(123) ["b"]=> object(B)#2 (1) { ["d"]=> NULL } } 
object(A)#3 (2) { ["a"]=> int(123) ["b"]=> object(B)#2 (1) { ["d"]=> NULL } } 

可以看到,$a1和$a2明显是两个不同的对象(对象标识符不同了)。但是需要留意的一点是,"b"指向的对象标识符都是#2,证明这两个对象是相同的,这就是“浅拷贝”的“缺陷”——但有时候这两个对象确实需要相同,所以PHP的clone默认是“浅拷贝”。

 

立即学习PHP免费学习笔记(深入)”;

为什么叫浅拷贝(shallow copy)?

因为在复制的时候,所有的属性都是“值传递”的,而上面的b属性存储的是对象标识符,所以相当于做了“引用传递”,这并不是完全的拷贝,所以称为“浅拷贝”。

 

立即学习PHP免费学习笔记(深入)”;

深拷贝

上面讲到,使用clone关键字的时候,会自动调用旧对象的__clone()方法(然后返回拷贝的对象),所以只需要在对应的类中重写__clone()方法,使返回的对象中的“引用传递”的属性指向另一个新的对象。以下是例子(可以比较“浅拷贝”的例子,其实就多了重写__clone()的步骤):

";
}

class B{
    public $d;
}

class A{
    public $a;
    public $b;

    public function d(){
        echo "A -> d";
    }

    public function __clone(){
        // clone自己
        $this->b = clone $this->b;
    }
}

$a1 = new A();
$a1->a = 123;
// 这里对象属性的值是一个对象示例,其实就是存储了对象标识符。使用clone关键字生成的拷贝中的b属性仍然指向旧对象的b属性指向的对象,这是"浅拷贝"出现的问题。如果需要指向一个新的对象,必须"深拷贝"
$a1->b = new B();

// PHP 5 only
$a2 = clone $a1;

dump($a1);
dump($a2);

 

立即学习PHP免费学习笔记(深入)”;

结果就不同了,注意b属性的对象标识符:

object(A)#1 (2) { ["a"]=> int(123) ["b"]=> object(B)#2 (1) { ["d"]=> NULL } } 
object(A)#3 (2) { ["a"]=> int(123) ["b"]=> object(B)#4 (1) { ["d"]=> NULL } } 

 

立即学习PHP免费学习笔记(深入)”;

PHP速学教程(入门到精通)
PHP速学教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
云朵浏览器入口合集
云朵浏览器入口合集

本专题整合了云朵浏览器入口合集,阅读专题下面的文章了解更多详细地址。

0

2026.01.20

Java JVM 原理与性能调优实战
Java JVM 原理与性能调优实战

本专题系统讲解 Java 虚拟机(JVM)的核心工作原理与性能调优方法,包括 JVM 内存结构、对象创建与回收流程、垃圾回收器(Serial、CMS、G1、ZGC)对比分析、常见内存泄漏与性能瓶颈排查,以及 JVM 参数调优与监控工具(jstat、jmap、jvisualvm)的实战使用。通过真实案例,帮助学习者掌握 Java 应用在生产环境中的性能分析与优化能力。

20

2026.01.20

PS使用蒙版相关教程
PS使用蒙版相关教程

本专题整合了ps使用蒙版相关教程,阅读专题下面的文章了解更多详细内容。

62

2026.01.19

java用途介绍
java用途介绍

本专题整合了java用途功能相关介绍,阅读专题下面的文章了解更多详细内容。

87

2026.01.19

java输出数组相关教程
java输出数组相关教程

本专题整合了java输出数组相关教程,阅读专题下面的文章了解更多详细内容。

39

2026.01.19

java接口相关教程
java接口相关教程

本专题整合了java接口相关内容,阅读专题下面的文章了解更多详细内容。

10

2026.01.19

xml格式相关教程
xml格式相关教程

本专题整合了xml格式相关教程汇总,阅读专题下面的文章了解更多详细内容。

13

2026.01.19

PHP WebSocket 实时通信开发
PHP WebSocket 实时通信开发

本专题系统讲解 PHP 在实时通信与长连接场景中的应用实践,涵盖 WebSocket 协议原理、服务端连接管理、消息推送机制、心跳检测、断线重连以及与前端的实时交互实现。通过聊天系统、实时通知等案例,帮助开发者掌握 使用 PHP 构建实时通信与推送服务的完整开发流程,适用于即时消息与高互动性应用场景。

19

2026.01.19

微信聊天记录删除恢复导出教程汇总
微信聊天记录删除恢复导出教程汇总

本专题整合了微信聊天记录相关教程大全,阅读专题下面的文章了解更多详细内容。

160

2026.01.18

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号