PHP关于foreach复制知识点总结

 更新时间:2019年01月28日 14:48:52   投稿:laozhang  
在本篇文章里小编给大家分享了关于PHP关于foreach复制知识点总结,有兴趣的朋友们学习下。

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可生成缩略图的文件上传类实例

    php可生成缩略图的文件上传类实例

    这篇文章主要介绍了php可生成缩略图的文件上传类,给出了完整的类文件代码及其相应的用法示例,非常具有实用价值,需要的朋友可以参考下
    2014-12-12
  • php实现XSS安全过滤的方法

    php实现XSS安全过滤的方法

    这篇文章主要介绍了php实现XSS安全过滤的方法,实例分析了php针对XSS进行安全过滤的相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-07-07
  • swfupload 多文件上传实现代码

    swfupload 多文件上传实现代码

    swfupload 采用flash+ajax方式上传文件
    2008-08-08
  • PHP将MySQL的查询结果转换为数组并用where拼接的示例

    PHP将MySQL的查询结果转换为数组并用where拼接的示例

    这篇文章主要介绍了PHP将MySQL的查询结果转换为数组并用where拼接的示例,这样处理where条件时便可以在一定程度上优化查询和转化的性能,需要的朋友可以参考下
    2016-05-05
  • PHP基于phpqrcode生成带LOGO图像的二维码实例

    PHP基于phpqrcode生成带LOGO图像的二维码实例

    这篇文章主要介绍了PHP基于phpqrcode生成带LOGO图像的二维码,可实现生成带logo与不带logo两种二维码的功能,非常简单实用,需要的朋友可以参考下
    2015-07-07
  • PHP大小写问题:函数名和类名不区分,变量名区分

    PHP大小写问题:函数名和类名不区分,变量名区分

    这篇文章主要介绍了PHP大小写问题,php中变量名是区分大小写的,而函数名与类名是不区分的
    2013-06-06
  • Yii中render和renderPartial的区别

    Yii中render和renderPartial的区别

    这篇文章主要介绍了Yii中render和renderPartial的区别,以下由我们在信易网络公司开发项目的时候终结出的一些经验
    2014-09-09
  • PHP Memcached应用实现代码

    PHP Memcached应用实现代码

    在很多场合,我们都会听到 memcached 这个名字,但很多同学只是听过,并没有用过或实际了解过,只知道它是一个很不错的东东。这里简单介绍一下,memcached 是高效、快速的分布式内存对象缓存系统,主要用于加速 WEB 动态应用程序。
    2010-02-02
  • php数组生成html下拉列表的方法

    php数组生成html下拉列表的方法

    这篇文章主要介绍了php数组生成html下拉列表的方法,涉及php根据数组动态创建html代码的相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-07-07
  • php使用curl实现ftp文件下载功能

    php使用curl实现ftp文件下载功能

    这篇文章主要为大家详细介绍了php使用curl实现ftp文件下载功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-05-05

最新评论