Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
4.2k views
in Technique[技术] by (71.8m points)

PHP对象复制奇怪问题

PHP对象复制奇怪问题

上代码

<?php

class Container
{
     public $data;
     public $index;
     public function __construct($data = null, $index = null)
     { 
        $this->data = $data;
         $this->index = $index;
     }
 }
 
class Nihao
{
     public $head;
     public $tail;
     public function __construct()
     { 
        $this->head = new Container();
        $this->tail = $this->head;
     }
     public function enqueue($data)
     { 
        $node = new Container($data);
        //第一次调用的时候我可以理解,PHP对象复制是浅复制
        //但是当第二次调用该方法时,理论上已经被赋值为$node了.
        $this->tail->index = $node;
        $this->tail = $node;
     }
 }
 
$nihao = new Nihao();
echo json_encode($nihao).PHP_EOL;
$nihao->enqueue(0);
echo json_encode($nihao).PHP_EOL;
$nihao->enqueue(1);
echo json_encode($nihao).PHP_EOL;

//{"head":{"data":null,"index":null},"tail":{"data":null,"index":null}}
//{"head":{"data":null,"index":{"data":0,"index":null}},"tail":{"data":0,"index":null}}
//{"head":{"data":null,"index":{"data":0,"index":{"data":1,"index":null}}},"tail":{"data":1,"index":null}}

问题:

我知道PHP的对象复制是浅复制,两个成员对象head和tail指向的是同一个对象,相互影响.

  1. 在第一次调用enqueue(0)的时候已经将tail赋值为一个全新的Container()对象,为什么这一步没有影响到head的值?
  2. 在第二次调用enqueue(1)的时候,退一万步讲,这时候tail已经在上次调用,也就是enqueue(1)的时候被修改了,为什么这次还可以影响到head?
  3. 而且为什么$this->tail->index = $node; 会自定把$node放到head的最后最内层?

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

浅复制就是引用赋值,用C语言解释就相当于指针,变量的值其实是对象的内存地址而非对象本身。

// head指向了Container对象的内存地址
$this->head = new Container();
// tail指向了head所指向的Container对象的内存地址,所以还是那个Container对象,你误以为tail指向的是head的内存地址,但是head是引用变量
$this->tail = $this->head;

在正式的编码中应该避免重复给成员赋引用值,一个成员应该始终指向同一个对象,也要避免多个成员变量指向同一个引用值。


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...