• [转载]php中深拷贝浅拷贝


    转自: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操作
    ";
    $b2=clone $b1;
    echo"b1的值
    ";
    echo "b1的info:{$b1->info}
    ";
    echo "b1的a的info:{$b1->a->info}
    ";
    echo"b2的值
    ";
    echo "b2的info:{$b2->info}
    ";
    echo "b2的a的info:{$b2->a->info}
    ";
    $b1->info="this value is updated(this is b)";
    $b1->a->info="this value is updated(this is a)";
    echo"修改b1后,b1的值
    ";
    echo "b1的info:{$b1->info}
    ";
    echo "b1的a的info:{$b1->a->info}
    ";
    echo"修改b1后,b2的值
    ";
    echo "b2的info:{$b2->info}
    ";
    echo "b2的a的info:{$b2->a->info}
    ";
    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是同一个对象。

    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操作
    ";
    $b2=clone $b1;
    echo "b1的值
    ";
    echo "b1的info:{$b1->info}
    ";
    echo "b1的a的info:{$b1->a->info}
    ";
    echo"b2的值
    ";
    echo "b2的info:{$b2->info}
    ";
    echo "b2的a的info:{$b2->a->info}
    ";
    $b1->info="this value is updated(this is b)";
    $b1->a->info="this value is updated(this is a)";
    echo"修改b1后,b1的值
    ";
    echo "b1的info:{$b1->info}
    ";
    echo "b1的a的info:{$b1->a->info}
    ";
    echo"修改b1后,b2的值
    ";
    echo "b2的info:{$b2->info}
    ";
    echo "b2的a的info:{$b2->a->info}
    ";
    echo"判断b1的a和b2的a是否为同一对象:" ,$b1->a===$b2->a, "
    ";
    ?>
    

      输出结果:

    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));//序列化然后反序列化
  • 相关阅读:
    codeforces #550D Regular Bridge 构造
    java学习路线-Java技术人员之路从0基础到高级
    iOSeasy造成循引用的场景
    Hybird App(一)----第一次接触
    PNP管理器简析--基于ReactOS0.33
    为什么寄存器比内存快?
    cookie 与 session 的差别、联系
    webstorm 配合IIS使用
    js实现可拉伸移动的div
    无法识别的属性“targetFramework”。请注意属性名称区分大小写
  • 原文地址:https://www.cnblogs.com/zhutianpeng/p/4262155.html
Copyright © 2020-2023  润新知