[英]PHP Class - assigning initiated class to a new variable
当我浏览PHP手册( http://php.net/manual/en/language.oop5.basic.php )时,遇到了以下困惑:
将已经创建的类的实例分配给新变量时,新变量将访问与分配的对象相同的实例。
并且下面的手册包含以下示例:
<?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"
}
如果第三种情况不应该也为NULL
新变量将访问与分配的对象相同的实例
否则,如果第一个启动器($ instance)设置为NULL并且$ assigned没有更改其值,则似乎$ assigned是按值传递的,而不是引用。
包含对象的变量实际上仅包含对象引用 。 可以将每个实例化的对象想像都生活在幕后某个对象的某个池中,还有一个变量仅包含诸如“ object#3”之类的对象的引用 。
如果通过=
将此对象引用分配给另一个变量,则会创建该引用的副本。 现在,两个变量保存了“ object#3”的副本,该副本显然引用了同一对象。
使用=&
通过引用进行分配会使两个变量指向同一个引用,因此,更改该引用的任何操作(如用null
覆盖它)都会影响这两个变量。 但是,该对象仍然在幕后继续存在,保留了对该对象的另一个引用的另一个变量不受影响。
更新:修改了图表和说明,以更准确地反映引擎盖下发生的情况。
在计算机语言中,变量被命名为用于存储值的存储位置。 在编译语言中,变量的名称通常在编译时消失。 它们只是程序员的语言帮助。 解释语言保留变量名,因为它们在运行时需要它们。
PHP将简单类型的值(布尔,整数,浮点数,字符串)存储在变量中; 它以不同的方式存储对象:分配了一个单独的存储块来存储对象数据,并且变量持有对象数据的引用/指针(存储对象数据的内存中的地址)。
对象分配不会复制对象数据; 它只是将数据的地址复制到一个新变量中。 为了复制对象的数据,必须使用clone
运算符,如下所示:
$duplicate = clone $instance;
编码:
$instance = new SimpleClass();
$assigned = $instance;
$reference =& $instance;
$duplicate = clone $instance;
$number = 123;
在内存中产生如下内容:
$instance
$reference
+----------------------+ +----------------------------+
| address of object #1 | --------> | SimpleClass object #1 data |
+----------------------+ +----------------------------+
^
$assigned |
+----------------------+ |
| address of object #1 | ------------------------+
+----------------------+
$duplicate
+----------------------+ +----------------------------+
| address of object #2 | --------> | SimpleClass object #2 data |
+----------------------+ +----------------------------+
$number
+------+
| 123 |
+------+
矩形是用于存储数据的存储位置。 其中一些在其上方显示名称(变量),而其他则没有(存储对象数据的内存块)。
这个怎么运作:
$instance = new SimpleClass();
分配一个内存块来存储一个SimpleClass
类型的新对象,并将对它的引用(其内存地址)存储在变量$instance
; $assigned = $instance;
将存储在变量$instance
的值(即对对象的引用)复制到新变量$assigned
; 这意味着$assigned
和$instance
指向同一类型SimpleClass
对象; 使用$instance->var
或$assigned->var
访问对象的属性是同一回事,因为它们都指向同一个SimpleClass
类型的实例; $reference = & $instance;
向名称$instance
标识的存储位置(变量)添加一个新名称( $reference
); $duplicate = clone $instance;
与$instance = new SimpleClass();
类似$instance = new SimpleClass();
但是新创建的对象不会通过调用其构造函数来初始化; 相反,将$instance
引用的对象的数据复制到新对象中,然后调用其方法__clone()
(如果存在); $instance = NULL;
会将变量$instance
的内容替换为NULL
(停止指向SimpleClass
对象#1),但不会影响$assigned
(它是一个不同的变量)或SimpleClass
对象#1本身; 仍然可以通过变量$assigned
访问该对象; $reference
将具有与$instance
相同的值,因为它们只是同一内存位置(现在存储NULL
)的名称。 数据结构现在看起来像:
$instance
$reference
+-------------------+ +----------------------------+
| NULL | | SimpleClass object #1 data |
+-------------------+ +----------------------------+
^
$assigned |
+----------------------+ |
| address of object #1 | ------------------------+
+----------------------+
$duplicate
+----------------------+ +----------------------------+
| address of object #2 | --------> | SimpleClass object #2 data |
+----------------------+ +----------------------------+
$number
+------+
| 123 |
+------+
unset($instance);
只是从变量中删除名称$instance
; 因为它仍然具有另一个名称( $reference
),所以该变量仍然存在,可以使用其另一个名称对其进行访问和修改。 当$reference
也未设置时,将无法再访问该变量,并且它使用的内存将在下一个垃圾回收周期释放。 当未设置$assigned
也会发生同样的情况(变量和对象数据均不可访问,它们将被释放)。
首先:-
用于垃圾回收的PHP用户引用计数方案,这意味着每次将一个对象变量分配给另一个对象时,该计数器将增加1,并且每次变量超出范围时,计数器将减少1
第二:-(通过变量传递变量)
$ a = 5; // //认为$ a的内存地址为25,或者我们可以说“ $ a”是指向位置25的指针,因此,每当我们在其中分配somethig或将其关联到其他位置时,我们都会获取此变量的位置,
如同
$ b = 10; //内部可能的内存地址是26
但重要的是:
$ a = 10; //内存地址25 $ b =&$ a; // $ b的内存地址也为25
所以如果我写$ a = 11; 因此,$ b的值也将更改,因为它们是同一内存位置的名称,所以当我更改一个时,它也会影响另一个,
现在谈论这个问题:
$instance = new SimpleClass();
在内存中创建对象的情况下,我们可以在地址“ x_address”上将其命名为“ x”,并且变量还创建名称$ instance,其位置为“ instance_address”,其中包含值“ x_adderss”,Refreence表如下所示:-
RefreenceTable:-
object | refrence_count | memory_address
| |
'x' | 1 | 'x_address'
和变量堆栈看起来像这样:-
堆栈:-
Variable_name | Variable_address | Variable_value
| |
instance | 'instance_address' | 'x_address'
现在下一个陈述
$assigned = $instance;
可变堆栈
Variable_name | Variable_address | Variable_value
| |
instance | 'instance_address' | 'x_address'
assigned | 'assigned_address' | 'x_address'
和
RefreenceTable:-
object | refrence_count | memory_address
| |
'x' | 2 | 'x_address'
因为现在2 varialbe引用了该对象,所以只有当这两个对象都超出范围时,该对象才会垃圾
下一条陈述
$reference = & $instance; // One of the most important line
可变堆栈
Variable_name | Variable_address | Variable_value
| |
instance | 'instance_address' | 'x_address'
assigned | 'assigned_address' | 'x_address'
refrence | 'instance_address' | 'x_address' // because pointing the same
// memory as instance
RefreenceTable:-
object | refrence_count | memory_address
| |
'x' | 2 | 'x_address'
注意没有增加ref_count,因为那个varialbe指向某个位置,换句话说,我们可以说现在我们可以使用两个名称指向location->'instance_address'
下一条声明:
$instance->var = '$assigned will have this value'; // Not so some changed happend in 'x_address'
下一条声明:
$instance = null; // one
重要线的
可变堆栈
Variable_name | Variable_address | Variable_value
| |
instance | 'instance_address' | NULL
assigned | 'assigned_address' | 'x_address'
refrence | 'instance_address' | NULL // because pointing the same
// memory as instance
Because instance and refrenced point to same location, if we change one values second will automaticallye changed, so both become null
但是对象'x'的refrence_count将减少1
RefreenceTable:-
object | refrence_count | memory_address
| |
'x' | 1 | 'x_address'
所以$ assigned仍然指向内存中的对象,
当我们这样写的时候:
$assigned = null;
然后
Variable_name | Variable_address | Variable_value
| |
instance | 'instance_address' | NULL
assigned | 'assigned_address' | NULL
refrence | 'instance_address' | NULL // because pointing the same
// memory as instance
object | refrence_count | memory_address
| |
'x' | 0 | 'x_address' // Marked for Garbe collection
谢谢:) {对不起,英语不好,我不是母语为英语的人}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.