zoukankan      html  css  js  c++  java
  • php内核中的变量

    php是弱类型语言,它可以保存任何的数据类型。但是php是使用c语言编写的,而c语言是强类型语言。每个变量都有固定的类型,不能随意改变变量的类型。

    在zend/zend.h中,查看结构体:

    zval结构体就是通常用到的php变量在内核总的表示形式,在zval结构体中,可以看到四个成员变量,分别是:

    zvalue_value value:变量的值,php变量的值就保存在这里。

    zend_uint refcount:变量引用数,变量引用计算器。

    zend_uchar type:变量的类型。

    zend_uchar  is_ref:变量是否被引用。

    zval结构体的value成员变量是zvalue_value联合体,php能够保持任何的结构类型就因为这个联合体。从zvalue_value联合体的成员变量中可以看到,不同的类型会保存到不同的成员变量中,这样就实现了php变量可以存储任何数据类型。例如,当变量是整数类型时,会保存到value的lval成员变量中,而当变量的类型是字符串时,又回保存到value的str成员变量中。

    以上是解决了php变量可以保存任意类型的问题,但是zend引擎是怎么知道这个变量保存的是什么类型呢,在zval结构中有个type成员变量,这个成员变量就是保存一个php变量的类型。

    我们都知道,php是不支持指针的,但是如果希望两个变量同事指向同一块内存怎么办?为了解决这个问题,php内核中使用了引用计数器。

    zval结构中有两个成员变量用于引用计数器:

    is_ref:bool值,标识变量是否是引用集合

    refcount:计算指向引用集合的变量个数

    <?php

    $a = "this is leju";

    ?>

    一个zval结构的实体称为zval容器,在php语言层创建一个变量就会相应的在php内核中创建一个zval容器。因为上面的代码创建了一个变量$a,所以在PHP内核中会创建一个zval容器。又因为这个变量不是一个引用,所以zval容器的is_ref等于false,并且refcount等于1.

    <?php

    $a = "this is leju";

    $b = $a;

    ?>

    上面这段代码中创建了两个变量  $a和$b,所以php内核中会创建两个zval容器来保存它们,变量b被赋予变量a的值,由于变量b并不是引用a,所以变量a的is_ref变量的值是false,但是使用xdebug打印变量a的话,会发现refcount等于2,这是为啥呢?

    首先来了解下php写时复制(copy on write)机制。

    写时复制是一个解决内存复用的方法,例如上面的代码,如果简单的把a的值赋值给b,那么就又两个 this is leju 字符串的复制,这样不利于内存的复用,因为完全可以使用一个 this is leju的字符串的复制完成工作,所以简单的赋值是非常耗内存的,写时复制就是为了解决这种问题而创造的,那什么是写时复制呢,就是当变量的值改变时才进行的内存的复制。

    当将变量a的值赋值给变量b时,变量a的refcount增加1,所以这时候变量a和变量b是指向同一内存块的,当改变变量a的值时,发现refcount的值变回1,所以这个时候变量a和变量b指向不同的内存块,这就是写时复制机制,就是两个指向同一内存块的变量,当其中一个变量的值发生变化,才会另外创建一个内存块去保存新的值,其实写时复制也是一种引用,只不过这种引用会受变量值的改变而破坏罢了。

    如果显示的引用变量,即$b = &a;变量的is_ref字段会设置1,表示此变量被引用,另外引用计数器(refcount)也相应的加1,在php内核中通过以下代码判断是否复制变量:

    if ((*varval)->is_ref || (*varval)->refcount < 2){

       return *varval;

    }

    推荐一本书,《PHP核心技术与最佳实践》 非常好看~

  • 相关阅读:
    吃推荐3个最近去了的好地方
    30岁生日
    今天开始试用Briglow Hair Cream
    WPF中如何在文本外面加虚线外框
    对账算法改进
    如何退出正在Sleep的线程
    关于framework4.5的相关介绍
    恐怖的报警邮件
    对帐引擎2个月后的监控数据
    wcf rest服务启用gzip压缩
  • 原文地址:https://www.cnblogs.com/weiluoyan/p/6940327.html
Copyright © 2011-2022 走看看