PHP中的对象分配

时间:2012-10-19 08:05:21

标签: php

首先,抱歉这个愚蠢的问题,但我正在阅读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。

但是分配了什么呢?它还指向存储$ instance的地方?为什么当我们使用$instance->var它会影响$ assigned,但是当我们将$ instance设置为null时,$ assigned没有变化?

我认为所有三个变量都指向记忆中的一个位置,但显然我错了。能否请您解释一下究竟发生了什么以及$分配了什么?非常感谢你!

7 个答案:

答案 0 :(得分:6)

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

另一方面,

$instance$instance值的副本,并且独立地指向$instance引用的对象本身。因此,当值null更新为指向空(即$assigned)时,$instance不受影响,因为它仍指向对象,并不关心内容{{1}}。

答案 1 :(得分:4)

设置$instance = null;不会更新$assigned,因为它不会更新$instance点所在位置的数据。而是修改$instance指针本身,使指针不再指向与$assigned相同的数据。

答案 2 :(得分:2)

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

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

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

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

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

&amp; operator实际上返回对它后面的变量的引用,所以当你写

$var1 = &var2;

然后$ var1也没有指向$ var2指向的对象,但$ var1指向$ var2本身。所以当你使$ var2为null时,$ var1指向同一个null。

答案 3 :(得分:2)

使用以下行,我们保留一个内存位置,其中存储新的Object和指针,标记为$instance

$instance = new SimpleClass();

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

$reference =& $instance;

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

$assigned = $instance;

通过将$instance设置为null,您只需将指针设置为包含实际对象的内存位置,而不是对象本身。对它的任何其他引用(例如,$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关键字显式复制。

答案 4 :(得分: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的属性发生了更改,也不会影响引用。

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

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

答案 5 :(得分:0)

正如您在代码中看到的那样

  

$ instance = null; // $ instance和$ reference变为null

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

答案 6 :(得分:0)

这很简单:

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

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

输出将是:

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

因此,不仅是对象分配,还有正常分配。