本文目录导读:

在 PHP 中,克隆对象时,默认情况下属性不会同步修改,但具体行为取决于属性的类型(值类型或引用类型)。
默认浅克隆(clone 关键字)
PHP 的 clone 关键字执行浅克隆(shallow copy):
class User {
public $name;
public $address; // 对象类型
public function __construct($name, $address) {
$this->name = $name;
$this->address = $address;
}
}
$address = new stdClass();
$address->city = 'Beijing';
$user1 = new User('Alice', $address);
$user2 = clone $user1;
// 修改 user2 的 name(值类型)
$user2->name = 'Bob';
echo $user1->name; // 输出 Alice(不受影响 ✅)
// 修改 user2 的 address(对象类型)
$user2->address->city = 'Shanghai';
echo $user1->address->city; // 输出 Shanghai(受影响 ❌)
不同属性类型的行为
| 属性类型 | 克隆后行为 | 示例 |
|---|---|---|
| 基本类型(int, string, bool) | 独立副本,修改互不影响 | |
| 数组 | 独立副本,但数组内的对象仍共享引用 | ⚠️ 需注意 |
| 对象 | 共享引用,修改会同步 | |
| 资源 | 行为依赖于资源类型,通常共享 |
数组的特殊情况
class Team {
public $members = [];
public function addMember($name) {
$this->members[] = new Person($name);
}
}
$team1 = new Team();
$team1->addMember('Alice');
$team2 = clone $team1;
$team2->members[0]->name = 'Bob';
echo $team1->members[0]->name; // 输出 Bob(受影响 ❌)
虽然数组本身是独立副本,但数组中的对象仍然是共享引用。
实现深克隆(__clone() 魔术方法)
如果需要完全独立的副本,必须在 __clone() 方法中手动复制引用类型的属性:
class User {
public $name;
public $address;
public function __clone() {
// 深克隆地址对象
$this->address = clone $this->address;
}
}
$user1 = new User('Alice', $address);
$user2 = clone $user1;
$user2->address->city = 'Shanghai';
echo $user1->address->city; // 输出 Beijing(不受影响 ✅)
序列化实现深克隆(另一种方法)
$user2 = unserialize(serialize($user1));
注意:
- 资源类型(如数据库连接)不能序列化
- 某些对象可能包含不能序列化的属性
- 性能开销较大
使用 clone vs 直接赋值
// 直接赋值 - 共享引用 $user2 = $user1; // 两个变量指向同一个对象 $user2->name = 'Bob'; echo $user1->name; // Bob(同步修改) // clone - 创建新对象 $user2 = clone $user1; // 独立对象 $user2->name = 'Bob'; echo $user1->name; // Alice(不修改)
- 默认
clone:基本类型独立,对象类型共享(浅克隆) - 需要深克隆:在
__clone()中显式克隆所有引用类型的属性 - 数组中的对象:注意它们仍然是共享引用
- 序列化方法:可以实现彻底深克隆,但有额外开销
最佳实践:根据业务需求选择合适的克隆策略,在处理复杂对象图时,考虑实现 __clone() 或使用专门的克隆工具类。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播