使用“new”实例化时到底发生了什么?
让我们考虑以下代码:
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)='你好' }
一一:
实例化到 $obj1 后:
obj1: (refcount=1, is_ref=0)=class a { public $var1 = (refcount=2, is_ref=0)=NULL }
为什么$obj1->var1
有refcount=2
当只有一个a类对象时?
是因为 new 运算符如何进行赋值吗? PHP 通过引用进行赋值。当使用new
实例化时,没有符号/变量名称与该实例关联。但是,类属性确实有名称。 recount=2
是因为这个吗?
如果是这种情况,则在类实例的浅拷贝 WRT 中发生了 COW(写时复制)。虽然属性仍然指向使用 new
实例化期间创建的属性的 zval。
现在,
将“Hello”分配给 $obj->var1 后:
你好obj1: (refcount=1, is_ref=0)=class a { public $var1 = (refcount=1, is_ref=0)='你好' }
因此,当我为属性 $obj1- 赋值时>var1
该属性的新 zval 容器以及 refcount=1
?
这是否意味着在实例化期间使用 new
创建的 zval 容器仍然存在,但由于没有与之关联的符号/变量名称而无法访问?
请注意(来自 xdebug:可变显示功能):debug_zval_dump()
与 xdebug_debug_zval()
不同。
void xdebug_debug_zval( [string varname [, ...]] )
显示有关变量的信息。
此函数显示有关一个或多个变量的结构化信息,包括其类型、值和引用计数信息。使用值递归地探索数组。此函数的实现方式与 PHP 的 debug_zval_dump() 函数不同,以便解决该函数存在的问题因为变量本身实际上传递给了函数。 Xdebug 的版本更好,因为它使用变量名称在内部符号表中查找变量并直接访问所有属性,而无需处理实际将变量传递给函数的情况。结果是,该函数返回的信息比 PHP 自己的显示 zval 信息的函数准确得多。
更新
:2011 年 12 月 31 日:
我试图了解使用 new 时如何进行内存分配。但现在我还有太多其他事情要做。我希望我能够尽快发布有用的更新。 在此之前,这里是我正在查看的代码链接:
Let's consider the following code:
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');
The output:
After instantiation into $obj1:
obj1: (refcount=1, is_ref=0)=class a { public $var1 = (refcount=2, is_ref=0)=NULL }After assigning "Hello" to $obj->var1:
Helloobj1: (refcount=1, is_ref=0)=class a { public $var1 = (refcount=1, is_ref=0)='Hello ' }
One by one:
After instantiation into $obj1:
obj1: (refcount=1, is_ref=0)=class a { public $var1 = (refcount=2, is_ref=0)=NULL }
Why does $obj1->var1
have refcount=2
when there is only one object of class a?
Is it because of how the new
operator makes assignment?
PHP does assignment with references. When instantiated with new
, no symbol/variable name is associated with that instance. But, the class properties do have names. Is the recount=2
because of this?
If that is the case then a C.O.W (copy on write) has occurred with a shallow copy WRT the class instance. While the properties are still pointing to the zval's of properties created during the instantiation using new
.
Now,
After assigning "Hello" to $obj->var1:
Helloobj1: (refcount=1, is_ref=0)=class a { public $var1 = (refcount=1, is_ref=0)='Hello ' }
So, when I assign a value to the property $obj1->var1
a new zval container for that property and hence the refcount=1
?
Does this mean that the zval container created during instantiation using new
still lives but cannot be accessed since there is no symbol / variable name associated with it?
Please note (from xdebug: Variable Display Features):debug_zval_dump()
is different from xdebug_debug_zval()
.
void xdebug_debug_zval( [string varname [, ...]] )
Displays information about a variable.
This function displays structured information about one or more variables that includes its type, value and refcount information. Arrays are explored recursively with values. This function is implemented differently from PHP's debug_zval_dump() function in order to work around the problems that that function has because the variable itself is actually passed to the function. Xdebug's version is better as it uses the variable name to lookup the variable in the internal symbol table and accesses all the properties directly without having to deal with actually passing a variable to a function. The result is that the information that this function returns is much more accurate than PHP's own function for showing zval information.
UPDATE
: Dec 31th 2011:
I am trying to look at how memory allocation takes place when new is used. But There are too many other things I have to do right now. I hope I will be able to post an useful update soon.
Until then here are the links to code at which I was looking at :
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
添加另一个实例化
$obj2 = new a;
将引用计数增加到 3,而不是 4,因此这是调用 xdebug_debug_zval 的结果。 xdebug 函数的目的是避免将变量传递到函数中并(可能)创建额外的引用而造成混乱。不幸的是,这不适用于成员变量;创建对这些 zval 的另一个引用以便导出它们。因此,debug_zval_dump 文档注释中列出的所有警告和令人困惑的情况仍然适用于成员变量。
Adding another instantiation
$obj2 = new a;
increases the refcount to 3, not 4, so it's something which happens as a result of calling xdebug_debug_zval. The purpose of the xdebug function is to avoid the confusion from the passing the variable into the function and (possibly) creating an extra reference.Unfortunately, this does not apply to the member variables; another reference is created to those zvals in order to export them. Therefore, all the caveats and confusing circumstances listed in the note on the debug_zval_dump documentation still apply for the member variables.
我认为下一页的“注意:注意引用计数”部分解释了这一点:
http://php.net/manual/en/function.debug-zval -dump.php
它表明,如果 zend 优化它的传递方式,引用计数会增加,但“警告”是在调用写时复制时,将引用计数返回到 1。
希望有帮助
I think the section "Note: Beware the refcount" on the following page explains this:
http://php.net/manual/en/function.debug-zval-dump.php
It shows that the ref count increases if zend optimizes how it's passed, but then the "caveat" being when copy-on-write is invoked, returning the refcount back down to 1.
Hope that helps