标题是不要在循环体中使用
array_push()
,其实这只是本篇文章的结论之一
下面我们一起研究一下php
语言中数组的追加元素
向数组追加元素
我们知道
php
在数组栈尾追加元素的方式有两种
$a = []; array_push($a,'test');
$a[] = 'test';
那么这两种方式有什么区别呢?
我们先来比较一下性能
ArrayPush
一个
ArrayPush
类
pushEachOne()
循环体中使用array_push()
来为$a
追加元素pushEachTwo()
循环体中使用$a[] = $var
来为$a
追加元素
1 | /** |
编写代码测试
循环追加 100 万个元素
1 | ini_set('memory_limit', '4000M'); |
结果
结果不言而喻,
$a[] =
比使用array_push()
快了接近三倍
1 | count pushEachOne result | 1000000 |
分析
array_push()为什么慢?这么慢,我们还有使用它的场景吗?
官方手册
array_push — 将一个或多个单元压入数组的末尾(入栈)
array_push ( array
&$array
, mixed$value1
[, mixed$...
] ) : intarray_push() 将
array
当成一个栈,并将传入的变量压入array
的末尾。array
的长度将根据入栈变量的数目增加。和如下效果相同:
1
2 > $array[] = $var;
>
并对每个传入的值重复以上动作。
Note: 如果用 array_push() 来给数组增加一个单元,还不如用 \$array[] = ,因为这样没有调用函数的额外负担。
Note: 如果第一个参数不是数组,array_push() 将发出一条警告。这和 \$var[] 的行为不同,后者会新建一个数组。
官方源码
看一下源码中的
array_push()
1 | /* {{{ proto int array_push(array stack, mixed var [, mixed ...]) |
$a[] =
的实现是根据赋值的变量类型调用了一系列 Zend_API
函数 add_next_index_*
,它们在设置一个对应类型的 zval 值以后直接调用了 zend_hash_next_index_insert
1 | ZEND_API int add_next_index_long(zval *arg, zend_long n) /* {{{ */ |
总结
经过上面的分析,仿佛 array_push()
没有任何存在的意义,真的是这样吗?
- 一般情况下,
array_push()
性能太差,所以我们应当使用$array[] =
来替换掉它 - 如果一次追加多个单元,使用
array_push()