PHP中的浅拷贝和深拷贝

简介:

深拷贝和浅拷贝的概念,一般程序员都很熟悉,网上的概念解析也很多。可以查看http://cnn237111.blog.51cto.com/2359144/589507

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

$a = clone $b;
这时候就得到a对象就复制了b对象。如果b对象中的成员都是值类型,那也就没什么关系,a对象中的成员和b变量中的成员都是各自占用独立的内存空间。但是由于这个克隆操作是浅拷贝,所以如果b的成员中有引用类型的数据,那么a对象的成员并未真正复制该成员,而是和b对象的成员共享了这一个对象。看下面的示例。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<?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操作<br>" ;
$b2 = clone  $b1 ;
echo "b1的值<br>" ;
echo  "b1的info:{$b1->info}<br>" ;
echo  "b1的a的info:{$b1->a->info}<br><br>" ;
echo "b2的值<br>" ;
echo  "b2的info:{$b2->info}<br>" ;
echo  "b2的a的info:{$b2->a->info}<br><br>" ;
$b1 ->info= "this value is updated(this is b)" ;
$b1 ->a->info= "this value is updated(this is a)" ;
echo "修改b1后,b1的值<br>" ;
echo  "b1的info:{$b1->info}<br>" ;
echo  "b1的a的info:{$b1->a->info}<br><br>" ;
echo "修改b1后,b2的值<br>" ;
echo  "b2的info:{$b2->info}<br>" ;
echo  "b2的a的info:{$b2->a->info}<br><br>" ;
echo "判断b1的a和b2的a是否为同一对象:"  , $b1 ->a=== $b2 ->a;
?>
运行结果如下:

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是同一个对象。

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<?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操作<br>" ;
$b2 = clone  $b1 ;
echo  "b1的值<br>" ;
echo  "b1的info:{$b1->info}<br>" ;
echo  "b1的a的info:{$b1->a->info}<br><br>" ;
echo "b2的值<br>" ;
echo  "b2的info:{$b2->info}<br>" ;
echo  "b2的a的info:{$b2->a->info}<br><br>" ;
$b1 ->info= "this value is updated(this is b)" ;
$b1 ->a->info= "this value is updated(this is a)" ;
echo "修改b1后,b1的值<br>" ;
echo  "b1的info:{$b1->info}<br>" ;
echo  "b1的a的info:{$b1->a->info}<br><br>" ;
echo "修改b1后,b2的值<br>" ;
echo  "b2的info:{$b2->info}<br>" ;
echo  "b2的a的info:{$b2->a->info}<br><br>" ;
echo "判断b1的a和b2的a是否为同一对象:"  , $b1 ->a=== $b2 ->a;
?>
运行完毕后,
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 is a

判断b1的a和b2的a是否为同一对象:

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

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

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

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
















本文转自cnn23711151CTO博客,原文链接:http://blog.51cto.com/cnn237111/1283163  ,如需转载请自行联系原作者

相关文章
|
7月前
|
关系型数据库 MySQL PHP
PHP 原生操作 Mysql
PHP 原生操作 Mysql
81 0
|
7月前
|
关系型数据库 MySQL 数据库连接
PHP 原生连接 Mysql
PHP 原生连接 Mysql
107 0
|
7月前
|
关系型数据库 MySQL Unix
PHP MySql 安装与连接
PHP MySql 安装与连接
125 0
|
3月前
|
关系型数据库 MySQL PHP
|
2天前
|
PHP
web简易开发——通过php与HTML+css+mysql实现用户的登录,注册
web简易开发——通过php与HTML+css+mysql实现用户的登录,注册
|
7月前
|
关系型数据库 MySQL 数据库连接
PHP 原生操作 Mysql 增删改查案例
PHP 原生操作 Mysql 增删改查案例
87 0
|
2月前
|
监控 关系型数据库 MySQL
PHP与MySQL的结合:实现局域网上网行为监控软件的数据库管理
在当今信息化时代,网络安全日益成为重要的话题。为了有效监控和管理局域网上网行为,开发一个基于PHP和MySQL的数据库管理系统是一个理想的选择。本文将介绍如何结合PHP和MySQL,开发一款简单而高效的局域网上网行为监控软件,并重点关注数据库管理方面的实现。
182 0
|
8月前
|
运维 关系型数据库 MySQL
【运维知识进阶篇】集群架构-Nginx实现基础web架构(Linux+Nginx+PHP+Mysql)(二)
【运维知识进阶篇】集群架构-Nginx实现基础web架构(Linux+Nginx+PHP+Mysql)(二)
198 0
|
8月前
|
消息中间件 NoSQL 关系型数据库
Linux安装 OpenResty、Nginx、PHP、Mysql、Redis、Lua、Node、Golang、MongoDB、Kafka等
Linux安装 OpenResty、Nginx、PHP、Mysql、Redis、Lua、Node、Golang、MongoDB、Kafka等
103 0