PHP Class - 将启动的 class 分配给一个新变量
PHP Class - assigning initiated class to a new variable
在阅读 PHP 手册 (http://php.net/manual/en/language.oop5.basic.php) 时,我遇到了以下困惑:
When assigning an already created instance of a class to a new variable, the new variable will access the same instance as the object that was assigned.
下面的手册包含以下示例:
<?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
the new variable will access the same instance as the object that was assigned
否则 $assigned 似乎是按值传递的,如果第一个启动器 ($instance) 设置为 NULL 并且 $assigned 没有更改其值,则不是引用。
一个包含对象的变量实际上只包含一个对象引用。将每个实例化的对象想象成生活在幕后某处的某个对象池中,并且一个变量只包含 "object#3" 之类的东西,对象的 引用 。
如果您通过 =
将此对象引用分配给另一个变量,则会创建此引用的副本。现在两个变量持有 "object#3" 的副本,这显然指的是同一个对象。
使用 =&
通过引用赋值使两个变量指向同一个引用,因此任何改变该引用的东西(比如用 null
覆盖它)都会影响这两个变量。尽管该对象仍然继续存在于幕后,但另一个持有对它的引用的变量不受影响。
更新: 修改了图表和解释以更准确地反映引擎盖下发生的事情。
在计算机语言中,变量被命名为用于存储值的内存位置。在编译语言中,变量名通常在编译时消失;它们只是程序员的语言辅助工具。解释型语言保留变量名,因为它们在运行时需要它们。
PHP 将简单类型(bool、integer、float、string)的值存储在变量中;它有不同的方式来存储对象:分配一个单独的内存块来存储对象数据,并且变量持有一个 reference/pointer 到对象数据(存储对象数据的内存地址)。
对象分配不复制对象数据;它只是将数据的地址复制到一个新变量中。为了复制对象的数据,必须像这样使用 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
;[=78中存储对它的引用(它的内存地址) =]
$assigned = $instance;
将存储在变量$instance
中的值(即对对象的引用)复制到新变量$assigned
中;这意味着 $assigned
指向与 $instance
类型相同的 SimpleClass
对象;使用 $instance->var
或 $assigned->var
访问对象的属性是一回事,因为它们都指向 SimpleClass
类型的同一个实例;
$reference = & $instance;
将新名称 ($reference
) 添加到由名称 $instance
; 标识的内存位置(变量)
$duplicate = clone $instance;
与$instance = new SimpleClass();
类似,但新创建的对象不是通过调用其构造函数来初始化的;相反,$instance
引用的对象的数据被复制到新对象中,然后调用其方法 __clone()
(如果存在);
$instance = NULL;
将用 NULL
替换变量 $instance
的内容(停止指向 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 的指针,所以每次我们在其中分配一些东西或将它分配给其他东西时,我们都在获取值这个变量的位置,
与
相同
$b = 10; // 可能是内部内存地址是 26
但重要的是:
$a = 10; //内存地址25
$b = &$a; // $b的内存地址也是25
所以如果我写 $a = 11;所以 $b 的值也会改变,因为它们是同一内存位置的名称,所以当我改变一个时,它也会影响其他,
现在说说这个问题:-
$instance = new SimpleClass();
这里在内存中创建了一个对象,我们可以在地址 'x_address' 上将其命名为 'x' 并且变量也创建名称 $instance 其位置是 'instance_address' 包含值 'x_adderss' 和 Refrence table 看起来像这样:-
参考表:-
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'
和
参考表:-
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
参考表:-
object | refrence_count | memory_address
| |
'x' | 2 | 'x_address'
注意 refrence _count 没有增加,因为指向某个位置的变量,换句话说,我们现在可以指向位置 -> 'instance_address' 和 2 个名称
下一条语句:
$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
参考表:-
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
谢谢 :) { 抱歉英语不好,我的母语不是英语}
在阅读 PHP 手册 (http://php.net/manual/en/language.oop5.basic.php) 时,我遇到了以下困惑:
When assigning an already created instance of a class to a new variable, the new variable will access the same instance as the object that was assigned.
下面的手册包含以下示例:
<?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"
}
如果
第三种情况不应该也是 NULLthe new variable will access the same instance as the object that was assigned
否则 $assigned 似乎是按值传递的,如果第一个启动器 ($instance) 设置为 NULL 并且 $assigned 没有更改其值,则不是引用。
一个包含对象的变量实际上只包含一个对象引用。将每个实例化的对象想象成生活在幕后某处的某个对象池中,并且一个变量只包含 "object#3" 之类的东西,对象的 引用 。
如果您通过 =
将此对象引用分配给另一个变量,则会创建此引用的副本。现在两个变量持有 "object#3" 的副本,这显然指的是同一个对象。
使用 =&
通过引用赋值使两个变量指向同一个引用,因此任何改变该引用的东西(比如用 null
覆盖它)都会影响这两个变量。尽管该对象仍然继续存在于幕后,但另一个持有对它的引用的变量不受影响。
更新: 修改了图表和解释以更准确地反映引擎盖下发生的事情。
在计算机语言中,变量被命名为用于存储值的内存位置。在编译语言中,变量名通常在编译时消失;它们只是程序员的语言辅助工具。解释型语言保留变量名,因为它们在运行时需要它们。
PHP 将简单类型(bool、integer、float、string)的值存储在变量中;它有不同的方式来存储对象:分配一个单独的内存块来存储对象数据,并且变量持有一个 reference/pointer 到对象数据(存储对象数据的内存地址)。
对象分配不复制对象数据;它只是将数据的地址复制到一个新变量中。为了复制对象的数据,必须像这样使用 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
;[=78中存储对它的引用(它的内存地址) =]$assigned = $instance;
将存储在变量$instance
中的值(即对对象的引用)复制到新变量$assigned
中;这意味着$assigned
指向与$instance
类型相同的SimpleClass
对象;使用$instance->var
或$assigned->var
访问对象的属性是一回事,因为它们都指向SimpleClass
类型的同一个实例;$reference = & $instance;
将新名称 ($reference
) 添加到由名称$instance
; 标识的内存位置(变量)
$duplicate = clone $instance;
与$instance = new SimpleClass();
类似,但新创建的对象不是通过调用其构造函数来初始化的;相反,$instance
引用的对象的数据被复制到新对象中,然后调用其方法__clone()
(如果存在);$instance = NULL;
将用NULL
替换变量$instance
的内容(停止指向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 的指针,所以每次我们在其中分配一些东西或将它分配给其他东西时,我们都在获取值这个变量的位置,
与
相同$b = 10; // 可能是内部内存地址是 26
但重要的是:
$a = 10; //内存地址25 $b = &$a; // $b的内存地址也是25
所以如果我写 $a = 11;所以 $b 的值也会改变,因为它们是同一内存位置的名称,所以当我改变一个时,它也会影响其他,
现在说说这个问题:-
$instance = new SimpleClass();
这里在内存中创建了一个对象,我们可以在地址 'x_address' 上将其命名为 'x' 并且变量也创建名称 $instance 其位置是 'instance_address' 包含值 'x_adderss' 和 Refrence table 看起来像这样:-
参考表:-
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'
和
参考表:-
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
参考表:-
object | refrence_count | memory_address
| |
'x' | 2 | 'x_address'
注意 refrence _count 没有增加,因为指向某个位置的变量,换句话说,我们现在可以指向位置 -> 'instance_address' 和 2 个名称
下一条语句:
$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
参考表:-
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
谢谢 :) { 抱歉英语不好,我的母语不是英语}