繁体   English   中英

PHP类-将启动的类分配给新变量

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM