对于count()常用的参数类型应该为数组 , 对于继承Countable的类暂不作讨论
数组实现方式为Hashtable , 直接看看他的结构吧
typedef struct _hashtable {
uint nTableSize;// hash Bucket的大?。钚∥?,以2x增长 。
uint nTableMask;// nTableSize-1 , 索引取值的优化
uint nNumOfElements;// hash Bucket中当前存在的元素个数,count()函数会直接返回此值
ulong nNextFreeElement; // 下一个数字索引的位置
Bucket *pInternalPointer;// 当前遍历的指针(foreach比for快的原因之一)
Bucket *pListHead;// 存储数组头元素指针
Bucket *pListTail;// 存储数组尾元素指针
Bucket **arBuckets;// 存储hash数组
dtor_func_t pDestructor;// 在删除元素时执行的回调函数,用于资源的释放
zend_bool persistent;//指出了Bucket内存分配的方式 。如果persisient为TRUE,则使用操作系统本身的内存分配函数为Bucket分配内存,否则使用PHP的内存分配函数 。
unsigned char nApplyCount; // 标记当前hash Bucket被递归访问的次数(防止多次递归)
zend_bool bApplyProtection;// 标记当前hash桶允许不允许多次访问,不允许时 , 最多只能递归3次
#if ZEND_DEBUG
int inconsistent;
#endif
} HashTable;
count直接获取nNumOfElements大?。?所以也是O(1)
补充------------------------------------------------
count() 函数的定义在这里
/* {{{ proto int count(mixed var [, int mode])
Count the number of elements in a variable (usually an array) */
PHP_FUNCTION(count)
{
zval *array;
zend_long mode = COUNT_NORMAL;
zend_long cnt;
zval *element;
ZEND_PARSE_PARAMETERS_START(1, 2)
Z_PARAM_ZVAL(array)
Z_PARAM_OPTIONAL
Z_PARAM_LONG(mode)
【php数据库count PHP数据库操作类】ZEND_PARSE_PARAMETERS_END();
switch (Z_TYPE_P(array)) {
case IS_NULL:
php_error_docref(NULL, E_WARNING, "Parameter must be an array or an object that implements Countable");
RETURN_LONG(0);
break;
case IS_ARRAY:
if (mode != COUNT_RECURSIVE) {
//类型为数组时调用zend内核函数 zend_array_count()
cnt = zend_array_count(Z_ARRVAL_P(array));
} else {
cnt = php_count_recursive(Z_ARRVAL_P(array));
}
RETURN_LONG(cnt);
break;
case IS_OBJECT: {
zval retval;
/* first, we check if the handler is defined */
if (Z_OBJ_HT_P(array)-count_elements) {
RETVAL_LONG(1);
if (SUCCESS == Z_OBJ_HT(*array)-count_elements(array, Z_LVAL_P(return_value))) {
return;
}
}
/* if not and the object implements Countable we call its count() method */
if (instanceof_function(Z_OBJCE_P(array), zend_ce_countable)) {
zend_call_method_with_0_params(array, NULL, NULL, "count", retval);
if (Z_TYPE(retval) != IS_UNDEF) {
RETVAL_LONG(zval_get_long(retval));
zval_ptr_dtor(retval);
}
return;
}
/* If There's no handler and it doesn't implement Countable then add a warning */
php_error_docref(NULL, E_WARNING, "Parameter must be an array or an object that implements Countable");
RETURN_LONG(1);
break;
}
default:
php_error_docref(NULL, E_WARNING, "Parameter must be an array or an object that implements Countable");
RETURN_LONG(1);
break;
}
}
如果没有特别指定mode参数为 COUNT_RECURSIVE 的话(即作遍历),跳转到 zend 的数组计数函数 zend_array_count()
#define zend_hash_num_elements(ht) \
(ht)-nNumOfElements
...
...
static uint32_t zend_array_recalc_elements(HashTable *ht)
{
zval *val;
uint32_t num = ht-nNumOfElements;
ZEND_HASH_FOREACH_VAL(ht, val) {
if (Z_TYPE_P(val) == IS_INDIRECT) {
推荐阅读
- 美女直播软件免费登陆,美女直播的软件有哪些?
- python3的pip库,python35 pip
- 三体游戏开发要多久,三体游戏开发要多久完成
- linux命令fsck linux命令行安装yum
- 安卓平板电脑i密码忘记了怎么办,安卓平板 忘记密码
- 台式显卡卡扣怎么打开教程,台式机显卡卡槽
- 学java写不出代码,java代码记不住怎么办
- python函数换行输出 python换行输出数据
- postgresql安装win7的简单介绍