PHP关于foreach复制知识点总结


Posted in PHP onJanuary 28, 2019

PHP的foreach是一个非常整洁和切中要害的语言结构。仍然有些人不喜欢使用它,因为他们认为它是缓慢的。一个通常命名的原因是foreach复制它迭代的数组。

因此,一些人建议写:

$keys = array_keys($array);
$size = count($array);
for ($i = 0; $i < $size; $i++) {
  $key  = $keys[$i];
  $value = $array[$key];
 
  // ...
}

而不是更直观和直接:

foreach ($array as $key => $value) {
  // ...
}

这里有两个问题:

Microoptimization是不好的。通常,它只会浪费您的时间,不会带来任何可度量的性能改进。

foreach的复制行为比大多数人认为的要复杂一些。通常情况下,“优化”的版本会比原始版本慢。

foreach什么时候复制?

foreach是否复制数组以及复制的数量取决于三件事:

是否引用了迭代数组、它的refcount有多高以及迭代是否通过引用完成。

没有引用,refcount == 1

在下面的代码中,$array没有被引用,并且refcount为1。在这种情况下,foreach不会复制数组(证明)——这与流行的观点相反,即foreach总是复制没有引用的迭代数组。

test();
function test() {
  $array = range(0, 100000);
  foreach ($array as $key => $value) {
    // ...
  }
}

原因很简单:为什么要这样做?foreach修改$array的唯一地方是它是内部数组指针。这是预期的行为,因此不需要预防。

未引用,refcount > 1

下面的代码看起来非常类似于前面的代码。唯一的区别是数组现在作为参数传递。这似乎是一个无关紧要的区别,但它确实改变了foreach的行为:

它现在将复制数组结构,而不是值(证明;如果你想知道这只是复制的结构,比较一下这个和那个脚本。第一个只复制结构,第二个两个都复制)。

$array = range(0, 100000);
test($array);
function test($array) {
  foreach ($array as $key => $value) {
    // ...
  }
}

乍一看这可能有点奇怪:

为什么当数组通过参数传递时,它会复制,但如果它是在函数中定义的,它就不会复制了?原因是数组zval现在在多个变量之间共享:函数外部的$array变量和函数内部的$array变量。如果foreach在不复制数组结构的情况下迭代数组,那么它不仅会改变函数中$array变量的数组指针,还会改变函数外$array变量的指针。因此foreach需要复制数组结构(即散列表)。另一方面,这些值仍然可以共享zvals,因此不需要复制。

引用

下一种情况与前一种情况非常相似。唯一的区别是数组是通过引用传递的。在这种情况下,数组将不会被复制(证明)。

$array = range(0, 100000);
test($array);
function test(&$array) {
  foreach ($array as $key => $value) {
    // ...
  }
}

在这种情况下,相同的推理适用于前一种情况:外部$数组和内部$数组共享zvals。不同的是,它们现在是引用(isref == 1),因此在这种情况下,对内部数组的任何更改都将对外部数组进行。所以如果内部数组的数组指针改变了,外部数组的数组指针也应该改变。这就是foreach不需要复制的原因。

迭代通过引用

上面的例子都是按值迭代的。对于引用迭代,应用相同的规则,但是附加值引用更改数组值的复制行为(关于结构复制的行为保持不变)。

情况“未引用,refcount == 1”没有改变。引用迭代意味着如果$值有任何变化,我们想要改变原始数组,这样数组就不会被复制(证明)。

“被引用”的情况也保持不变,在这种情况下,对$value的更改应该会更改引用迭代数组的所有变量(证明)。

只有“未引用,refcount > 1”的情况发生了变化,因为现在需要复制数组结构及其值。数组结构,因为否则函数外部的$array变量的数组指针会改变,而对$value的改变也会改变外部的$array值(证明)。

总结

当且仅当迭代数组未被引用且具有refcount > 1时,foreach将复制数组结构

foreach还将复制数组值,前提是且仅当上一个点应用并且迭代是通过引用完成时

PHP 相关文章推荐
一个用于MySQL的PHP XML类
Oct 09 PHP
IIS6.0+PHP5.x+MySQL5.x+Zend3.0x+GD+phpMyAdmin2.8x通用安装实例(已经完成)
Dec 06 PHP
php学习 函数 课件
Jun 15 PHP
php 常用类整理
Dec 23 PHP
解析PHP无限级分类方法及代码
Jun 21 PHP
使用openssl实现rsa非对称加密算法示例
Jan 24 PHP
php读取大文件示例分享(文件操作类)
Apr 13 PHP
PHP生成指定长度随机数最简洁的方法
Jul 14 PHP
PHP SplObjectStorage使用实例
May 12 PHP
php上传大文件设置方法
Apr 14 PHP
php实现构建排除当前元素的乘积数组方法
Oct 06 PHP
php高清晰度无损图片压缩功能的实现代码
Dec 09 PHP
实例讲解PHP验证邮箱是否合格
Jan 28 #PHP
PHP将英文数字转换为阿拉伯数字实例讲解
Jan 28 #PHP
PHP实现一个轻量级容器的方法
Jan 28 #PHP
PDO::_construct讲解
Jan 27 #PHP
PDO::commit讲解
Jan 27 #PHP
PDO::beginTransaction讲解
Jan 27 #PHP
PHP的PDO大对象(LOBs)
Jan 27 #PHP
You might like
四月新番又没了,《Re:从零开始的异世界生活》第二季延期至7月播出
2020/05/06 日漫
PHP查询MySQL大量数据的时候内存占用分析
2011/07/22 PHP
PHP中其实也可以用方法链
2011/11/10 PHP
PHP函数func_num_args用法实例分析
2015/12/07 PHP
PHP实现对二维数组某个键排序的方法
2016/09/14 PHP
浅谈laravel-admin form中的数据,在提交后,保存前,获取并进行编辑
2019/10/21 PHP
bgsound 背景音乐 的一些常用方法及特殊用法小结
2010/05/11 Javascript
input按钮的事件处理大全
2010/12/10 Javascript
IE的fireEvent方法概述及应用
2013/02/22 Javascript
Js控制弹窗实现在任意分辨率下居中显示
2013/08/01 Javascript
jquery库文件略庞大用纯js替换jquery的方法
2014/08/12 Javascript
用Jquery.load载入页面后样式没了页面混乱的解决方法
2014/10/20 Javascript
在AngularJS中使用AJAX的方法
2015/06/17 Javascript
Vue2 模板template的四种写法总结
2018/02/23 Javascript
node.js中fs文件系统目录操作与文件信息操作
2018/02/24 Javascript
结合Vue控制字符和字节的显示个数的示例
2018/05/17 Javascript
jQuery实现百度图片移入移出内容提示框上下左右移动的效果
2018/06/05 jQuery
Vue中在新窗口打开页面及Vue-router的使用
2018/06/13 Javascript
JS中的算法与数据结构之二叉查找树(Binary Sort Tree)实例详解
2019/08/16 Javascript
微信小程序 wx:for 与 wx:for-items 与 wx:key的正确用法
2020/05/19 Javascript
微信小程序仿抖音视频之整屏上下切换功能的实现代码
2020/05/24 Javascript
利用Django模版生成树状结构实例代码
2019/05/19 Python
Python openpyxl 插入折线图实例
2020/04/17 Python
Python本地及虚拟解释器配置过程解析
2020/10/13 Python
selenium自动化测试入门实战
2020/12/21 Python
CSS3实现简易版的刮刮乐效果
2016/09/27 HTML / CSS
世界上最受欢迎的钓鱼诱饵:Rapala
2019/05/02 全球购物
任课老师推荐信范文
2013/11/24 职场文书
防沙治沙典型材料
2014/05/07 职场文书
责任担保书范文
2014/05/21 职场文书
司法所长先进事迹
2014/06/02 职场文书
新闻学专业求职信
2014/07/28 职场文书
大学生思想道德自我评价
2015/03/09 职场文书
2015年妇幼卫生工作总结
2015/05/23 职场文书
2019餐饮行业创业计划书!
2019/06/27 职场文书
JS轻量级函数式编程实现XDM二
2022/06/16 Javascript