登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  文章 >  php教程

PHP SplFixedArray 缩容后超出范围的元素会怎样

来源:17golang原创

时间:2026-10-29 17:26:59 286浏览 收藏

PHP SplFixedArray 缩容时,新大小之外的元素会被丢弃。比如大小从4改为2,只保留下标0和1;原下标2和3不再有效。以后扩回4,新增位置补null,旧值不会自动找回来。

官方地址:https://www.php.net/

先划清容量调整的范围

我处理这类接口时,会先问“缩小的是可见窗口,还是容器本身”。SplFixedArray属于后者:setSize改变实际大小,并非隐藏尾部。本文采用容量调整前后对照的方式,讨论旧调用方如何修改,不把既有语义包装成新版本发布。

官方setSize文档明确说明缩小丢弃、扩大补null。需要恢复尾部的业务必须自己保存数据。setSize官方说明

缩容、越界与再次扩容分别意味着什么

操作容器状态调用方影响
4缩为2有效下标0、1停止访问旧尾部
读取下标2超出当前范围不能当作普通null槽位
2扩回4新位置为null恢复容量不等于恢复数据

无效索引读取会抛出RuntimeException,不能把它与范围内值为null混淆。循环若缓存缩容前的上界,就可能继续访问失效位置。offsetGet读取规则

固定数组容量与下标范围静态结构
静态说明图:保留区和截断区按新大小区分,不表示真实执行结果。

把需要保留的尾部先移出

我的取舍是让数据去向在代码里可见:业务确认需要丢弃就直接缩容;需要归档则先备份。下面示例未运行,说明预期语义,不提供实测输出。

getSize(); $i++) {
    $tail[$i] = $items[$i];
}
$items->setSize($newSize);
// 当前只访问有效下标,尾部数据从显式备份读取
var_dump($items->toArray(), $tail);
$items->setSize(4);
// 新增槽位补null,不会自动恢复east和west
var_dump($items->toArray());

按文档语义,第一次转换保留north、south,tail保存原下标2、3对应的值;再次扩容新增位置应为null。若要恢复,需显式回写tail,且先确保目标大小足够。不要在缩容后再尝试读取原尾部进行备份。

对象还活着为什么不代表槽位还在

如果被丢弃的值是对象,而另一个变量仍持有同一对象标识,对象仍可通过那个变量访问。这不意味着数组槽位存在,也不意味着扩容会把对象放回去。PHP对象赋值复制的是对象标识,并非自动克隆。对象与引用说明

因此,上面的尾部备份对对象并不是深复制快照。是否需要克隆以及如何复制嵌套对象,要由业务模型决定。我不会用“缩容后还能访问外部对象”作为数组保留尾部的证据,也不会据缩容承诺进程内存立即下降。

对象标识与外部变量、数组槽位的关系
静态说明图:外部持有者和容器槽位属于不同关系,槽位移除不等于所有对象持有者消失。

调整旧调用方的清单

  • 缩容前确定尾部是丢弃、归档还是迁移。
  • 更新缓存的循环上界,按当前大小访问。
  • 区分无效下标与有效位置的null。
  • 恢复操作同时考虑容量和数据回写。
  • 对象备份明确是否需要独立副本。

缩到0是不是清空全部元素?

容器不再有有效下标;后续重新扩容得到的是新增null位置,不是旧元素。

保存整个容器到另一个变量能当备份吗?

单纯对象赋值不能当独立容器快照,它可能仍指向同一个对象。需要保留内容时显式保存所需数据,并分别考虑元素对象的共享关系。

业务只是暂时少展示两项怎么办?

如果目标是展示窗口而非删除数据,可以保留容器,另外记录展示范围。我的建议是把“展示多少”和“容器保存多少”分开,避免把临时界面操作变成数据截断。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>