Php 为什么将此引用对象设置为NULL不会重置其所有副本?

Php 为什么将此引用对象设置为NULL不会重置其所有副本?,php,class,oop,Php,Class,Oop,当我们将NULL分配给$instance时,为什么$assigned没有变为NULL?当我们通过$instance->var更改$var的值时,$assigned将获得新的更新值 class SimpleClass { // property declaration public $var = 'a default value'; // method declaration public function displayVar() { echo

当我们将NULL分配给$instance时,为什么$assigned没有变为NULL?当我们通过$instance->var更改$var的值时,$assigned将获得新的更新值

class SimpleClass
{
    // property declaration
    public $var = 'a default value';

    // method declaration
    public function displayVar() {
        echo $this->var;
    }
}

$instance   = new SimpleClass();
$assigned   =  $instance;
$reference  =& $instance;

$instance->var = '$assigned will have this value';

$instance = null; // $instance and $reference become null

var_dump($instance);
var_dump($reference);
var_dump($assigned);
输出:

NULL
NULL
object(SimpleClass)#1 (1) {
   ["var"]=>
     string(30) "$assigned will have this value"
}

我使用的是PHP5.5.9。

我认为这是因为对象本身在为其标识符分配空值后仍然完好无损

当您设置对象的字段时(它位于对象的内存部分),但当您将其指针设置为另一个值时(它位于其他位置),因此对象本身仍然存在,并且可以被另一个标识符指针引用

这里有一个参考:

基础 要了解发生了什么,您需要深入了解php的内部结构,并了解如何管理内存

在引擎盖下,值表示如下:

+--------------------+
| (type) {{ VALUE }} |
| refcount = a       |
| isref = b          |
+--------------------+
参考计数器a统计指向该值的变量数。isref标志显示值是通过值分配的,即$a=value还是通过引用分配的,即$a=&value

让我们假设以下情况:

                 +--------------------------+
$a ------------->| (int) 58                 |          $a = 58
                 | refcount = 1 ; isref = 0 |
                 +--------------------------+
如果将$a的值复制到$b中,PHP只会增加refcount以提高内存效率,即不存储两倍于相同值的值:

                 +--------------------------+
$a -------+----->| (int) 58                 |          $b = $a
          |      | refcount = 2 ; isref = 0 |
          |      +--------------------------+
          |
          |
$b -------+
如果将$b的值更改为其他值,将创建一个新值,并将refcount减至58:

                 +--------------------------+
$a ------------->| (int) 58                 |          $b = 'hello'
                 | refcount = 1 ; isref = 0 |
                 +--------------------------+

                 +--------------------------+
$a ------------->| (string) 'hello'         |
                 | refcount = 1 ; isref = 0 |
                 +--------------------------+
对于引用,isref标志设置为true,并且更改会影响两个标识符:

                 +--------------------------+
$a -------+----->| (int) 58                 |          $b =& $a
          |      | refcount = 2 ; isref = 1 |
          |      +--------------------------+
          |
          |
$b -------+

关于对象引用 在PHP中,对象是通过引用透明地传递的,这不完全是真的。名称标识符$a包含一个对象标识符,这是函数之间传递的内容。我将在下面用一个object类型的整数来说明这个标识符,我不知道它到底是如何在引擎盖下完成的,但解释是正确的-

不要混淆标识符,即变量名和对象标识符,即内存中对象的编号

                 +--------------------------+
$a ------------->| (object) 547654764237685 |          $a = new FooBar();
                 | refcount = 1 ; isref = 0 |
                 +--------------------------+
在内存中的其他地方,PHP存储我们刚刚创建的带有标识符547654764237685的FooBar实例。当您使用值对象547654764237685时,PHP自动检索所述对象并允许您透明地使用它

发生了什么事? 让我们逐行检查您的代码

首先创建一个新的SimpleClass实例

                 +--------------------------+
$instance ------>| (object) 547654764237685 |          $instance = new SimpleClass();
                 | refcount = 1 ; isref = 0 |
                 +--------------------------+
然后对$assigned进行赋值,即增加refcount:

第三行引用$reference到$instance。由于该值的refcount大于1,并且它还不是引用isref=0,因此PHP在内存中创建了一个新的类似值:

                 +--------------------------+
$instance ---+-->| (object) 547654764237685 |          $reference =& $instance;
             |   | refcount = 2 ; isref = 1 |
             |   +--------------------------+
             |
             |
$reference --+

                 +--------------------------+
$assigned ------>| (object) 547654764237685 |
                 | refcount = 1 ; isref = 0 |
                 +--------------------------+
三个标识符$instance、$assigned和$reference对同一个对象求值,因为对象标识符保持不变。尽管如此,我们现在在内存中有两个不同的值

这就是调用$instance->var='$assigned将具有此值的原因;影响$instance->var、$assigned->var和$reference->var

现在,当您将$instance设置为null时,由于$reference引用相同的值,这两个值都会受到影响:

                 +--------------------------+
$instance ---+-->| (NULL)                   |          $instance = null;
             |   | refcount = 2 ; isref = 1 |
             |   +--------------------------+
             |
             |
$reference --+

                 +--------------------------+
$assigned ------>| (object) 547654764237685 |
                 | refcount = 1 ; isref = 0 |
                 +--------------------------+

$assigned的对象引用不受影响,因为它是一个单独的值,因此$assigned仍然调用该对象。

当我们将NULL赋值给$instance时,为什么$assigned没有变为NULL?因为它们是两个完全不同的变量,$assigned既不知道也不关心你对$instance做了什么。长期以来,你在这个网站上得到了一个最好的答案——是否愿意回复作者,或者至少接受作者?从你没有回复我,或者下面的优秀答案来看,我投了反对票。
                 +--------------------------+
$instance ---+-->| (object) 547654764237685 |          $reference =& $instance;
             |   | refcount = 2 ; isref = 1 |
             |   +--------------------------+
             |
             |
$reference --+

                 +--------------------------+
$assigned ------>| (object) 547654764237685 |
                 | refcount = 1 ; isref = 0 |
                 +--------------------------+
                 +--------------------------+
$instance ---+-->| (NULL)                   |          $instance = null;
             |   | refcount = 2 ; isref = 1 |
             |   +--------------------------+
             |
             |
$reference --+

                 +--------------------------+
$assigned ------>| (object) 547654764237685 |
                 | refcount = 1 ; isref = 0 |
                 +--------------------------+