【问题标题】:What is exactly happening when instantiating with 'new'?用“新”实例化时到底发生了什么?
【发布时间】:2012-01-29 22:03:14
【问题描述】:

让我们考虑以下代码:

class a {
    public $var1;
    function disp(){
        echo $this->var1;
        }    
    }

$obj1 = new a;
echo '<br/>After instantiation into $obj1:<br/>';    
xdebug_debug_zval('obj1');  

$obj1->var1 = "Hello ";
echo '<br/><br/>After assigning "Hello" to  $obj->var1:<br/>';
$obj1->disp();

echo "<br/><br/>";  
xdebug_debug_zval('obj1');  

输出:

实例化成$obj1后:
obj1: (refcount=1, is_ref=0)=class a { public $var1 = (refcount=2, is_ref=0)=NULL }

将“Hello”分配给 $obj->var1 后:
你好

obj1: (refcount=1, is_ref=0)=class a { public $var1 = (refcount=1, is_ref=0)='Hello ' }

一个接一个:

实例化成$obj1后:
obj1: (refcount=1, is_ref=0)=class a { public $var1 = (refcount=2, is_ref=0)=NULL }

当只有一个a类对象时,为什么$obj1-&gt;var1有refcount=2?

是不是因为new 操作符是怎么赋值的? PHP 使用引用进行赋值。当使用new 实例化时,没有符号/变量名称与该实例相关联。但是,类属性确实有名称。 recount=2是因为这个吗?

如果是这种情况,则发生了 C.O.W(写入时复制),并带有 WRT 类实例的浅拷贝。虽然属性仍然指向使用new 在实例化期间创建的属性的 zval。

现在,

将“Hello”分配给 $obj->var1 后:
你好

obj1: (refcount=1, is_ref=0)=class a { public $var1 = (refcount=1, is_ref=0)='Hello ' }

所以,当我为属性 $obj1-&gt;var1 分配一个值时,该属性的新 zval 容器以及 refcount=1?

这是否意味着在实例化期间使用new 创建的 zval 容器仍然存在,但由于没有与之关联的符号/变量名称而无法访问?

请注意(来自xdebug: Variable Display Features):
debug_zval_dump() 与xdebug_debug_zval() 不同。

void xdebug_debug_zval([string varname [, ...]])

显示有关变量的信息。

此函数显示有关一个或多个变量的结构化信息,包括其类型、值和引用计数信息。使用值递归地探索数组。该函数的实现方式与 PHP 的 debug_zval_dump() 函数不同,以便解决该函数所存在的问题,因为变量本身实际上是传递给函数的。 Xdebug 的版本更好,因为它使用变量名在内部符号表中查找变量并直接访问所有属性,而无需处理实际将变量传递给函数。结果是这个函数返回的信息比 PHP 自己的显示 zval 信息的函数要准确得多。

UPDATE:Dec 31th 2011:

我正在尝试查看使用 new 时如何进行内存分配。但是我现在要做的事情太多了。我希望我能尽快发布有用的更新。 在那之前,这里是我正在查看的代码链接:

【问题讨论】:

  • 也许 xdebug_debug_zval 创建了对相关对象的(临时)引用?
  • 基于question 进入我的脑海:但在 xdebug 的输出中,refcount 稍后仍然为 1。
  • 我没有具体的答案给你,但这个链接可能会对你有所帮助。 php.net/manual/en/features.gc.refcounting-basics.php
  • @Jrod 曾经读过那个链接。对于我的问题,那里没有任何可用的东西。

标签: php reference new-operator php-internals


【解决方案1】:

添加另一个实例化$obj2 = new a; 会将引用计数增加到 3,而不是 4,因此这是调用 xdebug_debug_zval 的结果。 xdebug 函数的目的是避免将变量传递给函数和(可能)创建额外的引用造成混淆。

很遗憾,这不适用于成员变量;为这些 zval 创建另一个引用以导出它们。因此,debug_zval_dump documentation 注释中列出的所有注意事项和令人困惑的情况仍然适用于成员变量。

【讨论】:

  • 是的,这就是我的推断。但我无法找到实质性的证据来支持它。
  • 看看xdebug_var.c:对象元素的变量导出处理输出。
【解决方案2】:

我认为下一页上的“注意:注意引用计数”部分解释了这一点: http://php.net/manual/en/function.debug-zval-dump.php

它表明如果 zend 优化了它的传递方式,则引用计数会增加,但是“警告”是在调用写时复制时,将引用计数返回到 1。

希望有帮助

【讨论】:

  • 来自 xdebug:Related Functions:debug_zval_dump() 与 xdebug_debug_zval() 不同。所以我无法得出你所说的推论。
  • 是的,请参阅问题中的更新信息。或我上面评论中发布的链接。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-21
相关资源
最近更新 更多