8

首先,很抱歉这个愚蠢的问题,但我正在阅读php.net中的一篇文章,但我无法理解它到底在说什么。

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

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



<?php

$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"
}

$instance 和 $reference 指向同一个地方,我明白了,我明白为什么我们会为它们得到 NULL 和 NULL。

但是 $assigned 呢?它还指向存储 $instance 的地方吗?为什么我们在使用$instance->var的时候会影响$assigned,但是当我们设置$instance为null时,对于$assigned却没有变化?

我以为这三个变量都指向内存中的一个地方,但显然我错了。您能否解释一下到底发生了什么以及 $assigned 是什么?非常感谢你!

4

7 回答 7

7

$reference指向 的$instance它本身就是一个对象的引用。因此,当您更改 所包含的值时$instance,会$reference反映此更改。

$assigned另一方面,它是的值的副本$instance,并且独立地指向所$instance引用的对象本身。因此,当值$instance更新为不指向任何内容(即null)时,$assigned不受影响,因为它仍然指向对象,并且不关心$instance.

于 2012-10-19T08:10:08.757 回答
4

设置$instance = null;不会更新$assigned,因为它没有更新指向位置的数据$instance。相反,它修改了$instance指针本身,使指针不再指向与 相同的数据$assigned

于 2012-10-19T08:08:15.947 回答
2

对象是内存中的一个独立实体,它可以有 1 个或多个引用。如果为 0,则为垃圾回收。

包含对象的变量实际上指向(引用)该对象。所以当你这样做时:

$var1 = new Object();
$var2 = $var1;

您只需创建两个变量,指向同一个对象($var2 复制 $var1 的值,但该值是对对象的引用)。

如果您随后编写, $var1 = null,则删除该引用,但 $var2 仍指向该对象。

& 运算符实际上返回对它后面的变量的引用,所以当你写

$var1 = &var2;

那么 $var1 并不指向 $var2 指向的对象,但 $var1 指向 $var2 本身。因此,当您将 $var2 设为 null 时,$var1 会指向同一个 null。

于 2012-10-19T08:11:32.097 回答
2

通过以下行,我们保留了一个内存位置,其中存储了新对象,以及一个指向它的指针,标记为$instance

$instance = new SimpleClass();

通过以下行,我们创建了对指针 $instance的引用,标记为$reference

$reference =& $instance;

使用以下代码,我们保留了一个新的内存位置,标记为$assigned,与上面的不同且独立,我们在其中存储了上面创建的指针(而不是对象本身)的副本:

$assigned = $instance;

通过设置$instancenull,您将仅取消设置指向包含实际对象的内存位置的指针,而不是对象本身。对它的任何其他引用(例如,$reference)也将被取消设置。

$assigned是指针的独立副本(保存在另一个内存位置),它仍然指向实际对象。

这就是为什么它仍然可以用来指代实际对象的原因。

PHP 文档中的这条评论支持上述内容:

<?php
class A {
    public $foo = 1;
}  

$a = new A;
$b = $a;
$a->foo = 2;
$a = NULL;
echo $b->foo."\n"; // 2

$c = new A;
$d = &$c;
$c->foo = 2;
$c = NULL;
echo $d->foo."\n"; // Notice:  Trying to get property of non-object...
?>

笔记

当谈到内存管理时,这代表了一种例外。而复制变量或数组仅通过使用=运算符来解决,对于对象,您应明确使用clone关键字,如 PHP 文档中所述:

PHP 中通常的按值赋值行为的一个例外发生在对象上,在 PHP 5 中通过引用进行赋值。对象可以通过 clone 关键字显式复制。

于 2012-10-19T08:18:32.377 回答
1

简短的回答,当您使用创建引用时&,会发生以下情况:

$A  ===+
       |===> [symbol table entry x] ====> (memory location)
$B  ===+

当你在那之后做一个正常的任务时:

$A  ===+
       |===> [symbol table entry x] ===> (memory location)
$B  ===+                                    ^
                                            |
$C  =======> [symbol table entry y] ========+

让我们逐步执行代码:

$instance = new SimpleClass();

$assigned   =  $instance;

断言:

$assigned === $instance

两者$assigned$instance引用相同的实例SimpleClass

$reference  =& $instance;

断言:

$assigned === $instance === $reference

所有变量都引用同一个实例。

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

断言:

$assigned === $instance === $reference

即使$instance更改了 of 的属性,它也不会影响引用。

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

因为$reference只是符号表中的一个别名,所以它的值与$instance;相同。原始实例(即内存位置)的引用计数减少到$assigned变量 1。

于 2012-10-19T08:42:11.797 回答
0

正如您在代码中看到的

$实例=空;// $instance 和 $reference 变为 null

$instance 现在已变为 null,但在此之前 $assigned 已设置。所以 $assigned 没有得到空值。$reference 收到了 null 值,因为您使用 =& 引用了它,它保留了 $instance 的值。

于 2012-10-19T08:10:28.393 回答
0

这真的很简单:

$a = 3;
$b = $a;
$c = &$a;
$a = 0;

var_dump($a);
var_dump($b);
var_dump($c);

输出将是:

int(0)
int(3)
int(0)

所以它不仅是对象赋值,也是正常赋值。

于 2012-10-19T08:48:34.443 回答