PHP数组基于哈希表实现动态扩容:当负载因子≥0.75时,按2的幂次扩容arData并重哈希;zval指针与引用计数保障内存安全;整数/字符串键统一哈希处理;空数组默认容量8,阶梯式翻倍增长;unset仅标记删除,不缩容。

PHP 中的数组本质上是哈希表(HashTable)结构,其设计允许在运行时动态添加元素而无需预先声明长度。以下是该机制的核心实现原理与关键环节:
一、哈希表底层结构支持动态扩容
PHP 数组并非传统 C 语言中的连续内存块,而是基于 HashTable 实现的键值容器。每个 HashTable 包含一个数据桶数组(arData)、容量(nTableSize)和已用数量(nNumOfElements)。当插入新元素导致负载因子超过阈值(默认为 0.75)时,系统自动触发扩容流程。
1、检查当前 arData 的已用槽位数与总槽数之比是否大于或等于 0.75。
2、若触发条件成立,则计算新的 nTableSize 值:向上取最接近的 2 的幂次(如原为 8,则扩为 16;原为 16,则扩为 32)。
立即学习“PHP免费学习笔记(深入)”;
3、分配一块大小为新 nTableSize 的 arData 内存区域。
4、将原有所有有效元素通过重新哈希(rehash)计算新索引位置,并复制到新 arData 中。
二、zval 与引用计数保障内存安全扩展
PHP 数组中存储的是 zval 结构体指针,而非原始数据副本。每个 zval 包含类型、值、refcount__gc 和 is_ref__gc 字段。动态扩展过程中,仅复制指针并更新 refcount,避免深拷贝开销,同时确保多处引用同一变量时不会误释放内存。
1、向数组追加新元素时,PHP 分配一个新的 zval 并初始化其 refcount__gc 为 1。
2、若该 zval 已被其他变量引用,则 refcount__gc 自增,原内存地址保持不变。
3、扩容期间遍历旧 arData,对每个非空 zval 指针执行 refcount__gc 加 1 操作。
4、旧 arData 释放前,对其所有 zval 执行 refcount__gc 减 1,仅当 refcount__gc 降为 0 时才真正释放对应值内存。
三、整数索引与字符串索引统一处理机制
PHP 数组同时支持数字下标与字符串键名,内部通过统一的 hash 函数(DJBX33A 变种)将键转换为无符号整型哈希值,并映射至 arData 索引。该机制屏蔽了键类型的差异,使任意类型键均可参与扩容逻辑,不依赖固定长度约束。
1、对于整数键(如 $arr[123]),直接以其绝对值作为哈希种子参与运算。
还木有评论哦,快来抢沙发吧~