转自:http://cnn237111.blog.51cto.com/2359144/1283163

PHP中提供了一种对象复制的操作,clone。语法颇为简单:

$a = clone $b;

1.浅拷贝

  上面的表达式得到a对象就是复制了b对象。如果b对象中的成员都是值类型,那也就没什么关系,a对象中的成员和b变量中的成员都是各自占用独立的内存空间。但是由于这个克隆操作是浅拷贝,所以如果b的成员中有引用类型的数据,那么a对象的成员并未真正复制该成员,而是和b对象的成员共享了这一个对象。看下面的示例。

<?php
class A
{
public $info="this is a";
}
class B
{
public $a;
function __construct()
{
$this->a=new A;
}
public $info="this is b";
}
$b1=new B();
echo "clone操作\n";
$b2=clone $b1;
echo"b1的值\n";
echo "b1的info:{$b1->info}\n";
echo "b1的a的info:{$b1->a->info}\n";
echo"b2的值\n";
echo "b2的info:{$b2->info}\n";
echo "b2的a的info:{$b2->a->info}\n";
$b1->info="this value is updated(this is b)";
$b1->a->info="this value is updated(this is a)";
echo"修改b1后,b1的值\n";
echo "b1的info:{$b1->info}\n";
echo "b1的a的info:{$b1->a->info}\n";
echo"修改b1后,b2的值\n";
echo "b2的info:{$b2->info}\n";
echo "b2的a的info:{$b2->a->info}\n";
echo"判断b1的a和b2的a是否为同一对象:" ,$b1->a===$b2->a, "\n";

输出结果:

clone操作
b1的值
b1的info:this is b
b1的a的info:this is a
b2的值
b2的info:this is b
b2的a的info:this is a
修改b1后,b1的值
b1的info:this value is updated(this is b)
b1的a的info:this value is updated(this is a)
修改b1后,b2的值
b2的info:this is b
b2的a的info:this value is updated(this is a)
判断b1的a和b2的a是否为同一对象:1

  可以看到,修改b1中引用类型a的值后,b2中的a的值也跟着变了。进一步,可以判断出b1的a和b2的a是同一个对象。

2.深拷贝

  和C++一样,php也提供了拷贝构造函数,以此可以自定义复制行为,实现深拷贝。PHP通过在对象的定义中实现__clone()方法来完成拷贝构造函数。这个函数在对象被复制的时候调用。还是之前的代码,修改一下。

<?php
class A
{
public $info="this is a";
}
class B
{
public $a;
function __construct()
{
$this->a=new A;
}
public $info="this is b"; public function __clone()
{
echo "拷贝构造函数开始调用<br>";
$new_object=new A;
$new_object->info=$this->a->info;
$this->a=$new_object;
}
}
$b1=new B();
echo "clone操作\n";
$b2=clone $b1;
echo "b1的值\n";
echo "b1的info:{$b1->info}\n";
echo "b1的a的info:{$b1->a->info}\n";
echo"b2的值\n";
echo "b2的info:{$b2->info}\n";
echo "b2的a的info:{$b2->a->info}\n";
$b1->info="this value is updated(this is b)";
$b1->a->info="this value is updated(this is a)";
echo"修改b1后,b1的值\n";
echo "b1的info:{$b1->info}\n";
echo "b1的a的info:{$b1->a->info}\n";
echo"修改b1后,b2的值\n";
echo "b2的info:{$b2->info}\n";
echo "b2的a的info:{$b2->a->info}\n";
echo"判断b1的a和b2的a是否为同一对象:" ,$b1->a===$b2->a, "\n";
?>

  输出结果:

clone操作
拷贝构造函数开始调用<br>b1的值
b1的info:this is b
b1的a的info:this is a
b2的值
b2的info:this is b
b2的a的info:this is a
修改b1后,b1的值
b1的info:this value is updated(this is b)
b1的a的info:this value is updated(this is a)
修改b1后,b2的值
b2的info:this is b
b2的a的info:this is a
判断b1的a和b2的a是否为同一对象:

  最后可以看到,b1的a和b2的a同一个对象是false,所以打印了一个空字符串。

————————————————————————

  上面的方法实现了魔法方法__clone,在这个方法中定义自己的深拷贝方式,这种写法比较麻烦,如果对象修改了,这个方法也得修改。事实上对成员进行深拷贝,可以采用将对象序列化后再还原的方式。这种写法可能性能上有所损失,但是确实最便捷的。PHP中,使用如下语句实现深拷贝:

  $b2 = unserialize(serialize($b1));//序列化然后反序列化

[转载]php中深拷贝浅拷贝的更多相关文章

  1. java中深拷贝浅拷贝简析

    Java中对象的创建 clone顾名思义就是复制, 在Java语言中, clone方法被对象调用,所以会复制对象.所谓的复制对象,首先要分配一个和源对象同样大小的空间,在这个空间中创建一个新的对象.那 ...

  2. 【转】JAVA中的浅拷贝和深拷贝

    原文网址:http://blog.bd17kaka.net/blog/2013/06/25/java-deep-copy/ JAVA中的浅拷贝和深拷贝(shallow copy and deep co ...

  3. Javascript中的浅拷贝和深拷贝

    很多开发语言中都有浅拷贝和深拷贝的说法,这里简单区分一下它们在Javascript中的区别,以及jQuery中深拷贝的实现. 在谈浅拷贝和深拷贝之前,先要屡清楚Javascript中的按值访问和按引用 ...

  4. python中深拷贝和浅拷贝

    python中所谓浅拷贝就是对引用的拷贝,所谓深拷贝就是对对象的资源的拷贝. 首先,对赋值操作我们要有以下认识: 赋值是将一个对象的地址赋值给一个变量,让变量指向该地址( 旧瓶装旧酒 ). 修改不可变 ...

  5. C# 中的浅拷贝与深拷贝

    Ø  简介 在 C# 中分为两种数据类型,值类型和引用类型.我们知道,值类型之间赋值是直接将值赋值给另一个变量,两个变量值的改变都互不影响:而引用类型赋值则是将引用赋值给另一个变量,其中一个变量中的成 ...

  6. python中的浅拷贝,深拷贝

    直接引用,间接引用 # 1.列表存储的是索引对应值的内存地址,值会单独的开辟一个内存空间 list = ["a","b"] 内存里面存储的就是list[0],l ...

  7. c# 内存的具体表现- 通用类型系统 深拷贝 浅拷贝 函数传参

    c# 通用类型系统 及变量在 深拷贝 浅拷贝 函数传参 中的深层次的表现 在编程中遇到了一些想不到的异常,跟踪发现,自己对于c#变量在内存上的表现理解有偏差,系统的学习并通过代码实验梳理了各种情况下, ...

  8. JavaScript之深拷贝&浅拷贝

    深拷贝&浅拷贝,说起来都明白,但是说不出所以然.今天就系统的整理下思绪,一点点的将其分析出所以然 废话不多说 浅拷贝 简单的说就是一个值引用,学生时代接触过编程的人都应该了解过指针,浅拷贝可以 ...

  9. 【opencv】imread 赋值 深拷贝浅拷贝

    import cv2 import copy import os def filter_srcimg(dstimg): ss=3 srcimg=copy.deepcopy(dstimg) #aa=5 ...

随机推荐

  1. 彻底理解Python中的yield

    阅读别人的python源码时碰到了这个yield这个关键字,各种搜索终于搞懂了,在此做一下总结: 通常的for…in…循环中,in后面是一个数组,这个数组就是一个可迭代对象,类似的还有链表,字符串,文 ...

  2. 【07】像使用命令行一样使用 GitHub URL

    [07] 像使用命令行一样使用 GitHub URL 既然说到了 URL,那么久接着聊一下.使用 UI 浏览 GitHub 很 方面也很好,不过很多时候最快的方式是使用 URL 来浏览.举个例子,如果 ...

  3. HDU 3947 River Problem

    River Problem Time Limit: 2000ms Memory Limit: 65536KB This problem will be judged on HDU. Original ...

  4. python3--__call__拦截调用

    __call__拦截调用 当实例调用时,使用__call__方法.不,这不是循环定义:如果定义了,Python就会为实例应用函数调用表达式运行__call__方法.这样可以让类实例的外观和用法类似于函 ...

  5. 编辑被标记为“只读”的Word文档

    从邮件接收到的Word文档,打开时总是被标记为“只读”,在阅读时对其进行编辑,但不能保存,会提示文档为只读的.要想对其进行编辑并保存,需要进行一定的操作. 进入文件所在的目录,鼠标右键点击Word文档 ...

  6. 2.ruby基本语法,类的定义

    1.在ruby中的定义class,ruby中定义类也是以关键字class开头 后面带着类名,类名以大写开头.一个类的结束以关键字end 结束.如: class Customer end 2.ruby类 ...

  7. BZOJ 4650 [Noi2016]优秀的拆分 ——后缀数组

    我们只需要统计在某一个点开始的形如$AA$字符串个数,和结束的个数相乘求和. 首先枚举循环节的长度L.即$\mid (A) \mid=L$ 然后肯定会经过s[i]和[i+L]至少两个点. 然后我们可以 ...

  8. Spoj-BITDIFF Bit Difference

    Given an integer array of N integers, find the sum of bit differences in all the pairs that can be f ...

  9. 设置java、maven环境变量(怕麻烦以后直接来这里复制)

    这种方法更为安全,它可以把使用这些环境变量的权限控制到用户级别,如果你需要给某个用户权限使用这些环境变量,你只需要修改其个人用户主目录下的.bash_profile文件就可以了. ·用文本编辑器打开用 ...

  10. Python入门--11--自定义函数

    使用def定义自定义函数 举个栗子: def myfristFunction(): print "we are 伐木累!" #输入myfristFunction() 会输出:we ...