PHP参考数组键 [英] PHP Reference in array key

查看:169
本文介绍了PHP参考数组键的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

PHP:

$a = array("key" => 23);
var_dump($a);

$c = &$a["key"];
var_dump($a);

unset($c);
var_dump($a);

输出:

array(1) {
  ["key"]=>
  int(23)
}
array(1) {
  ["key"]=>
  &int(23)
}
array(1) {
  ["key"]=>
  int(23)
}

在第二个转储钥匙的值被示出作为参考。这是为什么?
如果我做同样的普通变量而不是数组键不会发生这种情况。

In the second dump the value of "key" is shown as a reference. Why is that? If I do the same with a normal variable instead of an array key this does not happen.

我的唯一解释是数组键通常是存储作为参考,并且只要有在符号表中只有一个条目它被示为在转储一个标量。

My only explanation would be that array keys are usually stored as references and as long as there is only one entry in the symbol table it is shown as a scalar in the dump.

推荐答案

在内部,PHP​​阵列(无论你怎么称呼它,或者字典,哈希表或)包含HashMap。即使是一个数字索引数组实现为哈希表,这是一个的zval ,就像任何其他的。结果
然而,你看到的是预期的行为,这既是这里解释和的这里

Internally, PHP arrays are hashmaps (or dictionaries, or HashTables or whatever you want to call it). Even a numerically indexed array is implemented as a hash table, which is a zval, just like any other.
However, what you're seeing is expected behaviour, which is explained both here and here.

基本上,你的阵列看起来像内部是这样的:

Basically, what your array looks like internally is this:

typedef struct _zval_struct {
    zvalue_value value;
    zend_uint refcount__gc;
    zend_uchar type;
    zend_uchar is_ref__gc;
} zval;
//zval_value:
typedef union _zvalue_value {
    long lval;
    double dval;
    struct {
        char *val;
        int len;
    } str;
    HashTable *ht;
    zend_object_value obj;
} zvalue_value;

在数组的情况下, zval.type 将被设置为表明的zval 值是一个数组,所以 zval_value.ht 成员将被使用。结果
当你写会发生什么 $ c =&放大器;美元['关键'] 是,的zval 分配到 $一个['关键'] 将被更新: zval.refcount__gc 将会增加,而 is_ref__gc 将被设置为1,仅仅是因为的的是不可复制的,但价值被用于超过1变量:意味着此值的的参考。一旦你未设置($ C); 引用计数递减,参考丢失,等等 is_ref 设置为 0

In case of an array, the zval.type will be set to indicate that the zval value is an array, and so the zval_value.ht member will be used.
What happens when you write $c = &$a['key'] is that the zval that is assigned to $a['key'] will be updated: zval.refcount__gc will be incremented, and is_ref__gc will be set to 1. Simply because the value is not copied, but the value is used by more than 1 variable: meaning this value is a reference. Once you unset($c);, the refcount is decremented, and the reference is lost, and so is_ref is set to 0.

现在的大单:为什么你不明白,当你使用常规,标量变量是一回事吗?嗯,这是因为数组是一个Hashtable,完成了自己的内部,裁判计数( zval_ptr_dtor )。一旦一个数组本身是空的,它也应被销毁。通过创建一个数组值的引用,你取消设置阵,的zval 应GC'ed。但是,这将意味着你必须要引用的破坏的zval 左右浮动。结果
因此,在的zval 阵列中被改变为参考,也:基准可以安全地被删除。因此,如果你做到这一点:

Now for the big one: Why don't you see the same thing when you use regular, scalar variables? Well, that's because an array is a HashTable, complete with its own, internal, ref-counting (zval_ptr_dtor). Once an array itself is empty, it too should be destroyed. By creating a reference to an array value, and you unset the array, the zval should be GC'ed. But that would mean you have a reference to a destroyed zval floating around.
Therefore, the zval in the array is changed to a reference, too: a reference can be deleted safely. So that if you were to do this:

$foo = array(123);
$bar = &$foo[0];
unset($foo[0]);
echo $bar, PHP_EOL;

您code仍将按预期: $ foo的[0] 不再存在,但 $栏是现在唯一的参考现有的123。

Your code will still work as expected: $foo[0] no longer exists, but $bar is now the only existing reference to 123.

这仅仅是一个真的,真的,短和不完整的解释,但谷歌的PHP内部,以及内存管理是如何工作的,引用是如何内部处理,以及垃圾收集器如何使用 is_ref 引用计数成员来管理内存。结果
要特别注意像写入时复制的内部机制,以及(翻翻我这里提供的第一个链接时),寻找看起来像这样的片段:

This is just a really, really, short and incomplete explanation, but google the PHP internals, and how the memory management works, how references are dealt with internally, and how the garbage collector uses the is_ref and refcount members to manage the memory.
Pay special attention to the internal mechanisms like copy-on-write, and (when looking through the first link I provided here), look for the snippet that looks like this:

$ref = &$array;
foreach ($ref as $val) {}

由于它与文献和数组方面有一些古怪的交易。

Because it deals with some oddities in terms of references and arrays.

这篇关于PHP参考数组键的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆