clone只做浅拷贝,深拷贝需手动在__clone()中实现;serialize/unserialize是兜底方案但有性能和兼容性缺陷;并非所有属性都应深拷贝,须按语义逐个判断处理方式。

clone 关键字本身不能实现深拷贝,它只做浅拷贝;所谓“配合函数实现深拷贝”,实际是靠手动在 __clone() 方法里调用 clone 或其他逻辑完成的。
clone 默认只做浅拷贝,引用属性仍共享
PHP 中执行 $copy = clone $obj; 时:
- 所有标量属性(
string、int、bool等)被复制一份新值 - 所有对象属性(如
$this->config、$this->address)仍指向原对象里的同一实例 - 数组里的对象元素也不自动克隆,只是复制数组结构和引用
这意味着修改 $copy->config->host,$obj->config->host 也会变 —— 这不是你想要的“独立副本”。
__clone() 是唯一可控入口,必须手动处理嵌套对象
只要类定义了 __clone() 方法,PHP 就会在浅拷贝完成后立即调用它。这是你插入深拷贝逻辑的唯一合法时机:
if (is_object($this->config)) { $this->config = clone $this->config; }-
if ($this->handler instanceof Closure) { $this->handler = null; }(Closure不可克隆) if (is_array($this->items)) { foreach ($this->items as $k => $v) { if (is_object($v)) $this->items[$k] = clone $v; } }
注意:不能无脑递归调用 clone,遇到循环引用(A→B→A)会直接 fatal error。
serialize/unserialize 不是函数,是兜底方案,有硬伤
有人用 unserialize(serialize($obj)) 代替手写 __clone(),但它不是“函数配合 clone”,而是绕过 clone 的替代路径:
- 要求所有嵌套类支持序列化(即没含
resource、PDO、Closure等不可序列化类型) - 类若定义了
<strong>sleep()</strong>/wakeup(),行为可能被干扰 - 性能差:大对象序列化开销比手写
__clone()高 3–10 倍 - 私有/保护属性虽能保留,但类结构变更后反序列化可能失败
深拷贝不是语言特性,是业务需求驱动的手动工程。最容易被忽略的是:不是所有属性都该深拷贝,比如日志处理器、数据库连接、事件监听器,克隆后反而会引发资源冲突或内存泄漏。得逐个判断每个属性的语义,再决定是 clone、重建、置空,还是抛异常。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











