background image

我们注意到

, 最后一个元素, 这个是 flexible 

array

技巧

, 可以节省内存,和方便初始化的一种做

, 有兴趣的朋友可以 google flexible 

array

h 是元素的 Hash 值,对于数字索引的元素,h 为直接索引值(通过 nKeyLength=0 来表示是数字
索引

).而对于字符串索引来说, 索引值保存在 arKey 中, 索引的长度保存在 nKeyLength 中. 

Bucket 中,实际的数据是保存在 pData 指针指向的内存块中,通常这个内存块是系统另

外分配的。但有一种情况例外,就是当

Bucket 保存 的数据是一个指针时,HashTable 将不会

另外请求系统分配空间来保存这个指针,而是直接将该指针保存到

pDataPtr 中,然后再将

pData 指向本结构成员的地址。这样可以提高效率,减少内存碎片。由此我们可以看到 PHP 
HashTable 设计的精妙之处。如果 Bucket 中的数据不是一个指针,pDataPtr 为 NULL(本段来

Altair 的”Zend HashTable 详解”) 

结合上面的

HashTable 结构, 我们来说明下 HashTable 的总结构图: 

 
HashTable 的 pListhHead 指向线性列表形式下的第一个元素, 上图中是元素 1, pListTail 指向
的是最后一个元素

0, 而对于每一个元素 pListNext 就是红色线条画出的线性结构的下一个

元素

, 而 pListLast 是上一个元素. 

 
pInternalPointer 指向当前的内部指针的位置, 在对数组进行顺序遍历的时候, 这个指针指明
了当前的元素

 
当在线性

(顺序)遍历的时候, 就会从 pListHead 开始, 顺着 Bucket 中的 pListNext/pListLast, 根

据移动

pInternalPointer, 来实现对所有元素的线性遍历. 

 
比如

, 对于

foreach

, 如果我们查看它生成的 opcode 序列, 我们可以发现, 在

foreach

之前

, 会首

先有个

FE_RESET 来重置数组的内部指针, 也就是 pInternalPointer(关于

foreach

可以参看深

入理解

PHP 原理之

foreach

), 然后通过每次 FE_FETCH 来递增 pInternalPointer,从而实现顺序