首先,抱歉这个愚蠢的问题,但我正在阅读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没有变化?
我认为所有三个变量都指向记忆中的一个位置,但显然我错了。能否请您解释一下究竟发生了什么以及$分配了什么?非常感谢你!
答案 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)
因此,不仅是对象分配,还有正常分配。