PHP变量在内存中的存储方式
原文:http://www.phppan.com/tag/refcount/
每门计算机语言都需要一些容器来保存变量数据。在一些语言当中,变量都有特定的类型,如字符串,数组,对象等等。比如C和Pascal就属于这种。 而PHP则没有这样的类型。在PHP中,一个变量在某一行是字符串,可能到下一行就变成了数字。变量可以经常在不同的类型间轻易的转化,甚至是自动的转 换。PHP之所以成为一个简单并且强大的语言,很大一部分的原因是它拥有弱类型的变量。但是有些时候这也会带来一些有趣的问题。
在PHP内部,变量是存储在一个叫做zval的容器中。它不仅仅包含变量的值,也包含变量的类型。Python和PHP类似,也有一个标签标记变量类型。变量容器中包含一些Zend引擎用来区分是否引用的字段。同时它也包含这个值的引用计数。
变量存储在一个相当于关联数组的符号表中。这个数组以变量名为key,并且指向包含了这些变量的容器。如下图所示:
引用计数
PHP试着在变量拷贝(如 $a = $b )的时候变得聪明些。“=”也称为赋值操作符。当进行赋值操作时,Zend引擎不会创建一个新的变量窗口,而是增大变量窗口的 refcount 字段,你可以想象一下,当这个变量是一个巨大的字符串或一个巨大 的数组时,这将节约多少的内存。如下图所示:
第一步: 变量a,包含文本”this is”。默认情况下,引用计数等于1
第二步:将变量$a赋值给$b和$c。这里没有新的变量容器生成,仅仅是每次在变量赋值操作时将refcount加1。因为这里执行了两次赋值操作,所以refcount最后会变成3。
现在,也许你很想知道当变量$c改变时将发生什么。根据refcount的值的不同,它会有两种不同的处理方式。如果 refcount等于1,这个变量容器将更新它的值(也许同时会更新它的类型)。如果refcount大于1,将创建一个包含了新值(和类型)的变量容 器。如图2所示的第三步,$a变量所在的变量容器的refcount值被减去一,现在refcount的值是2,而新创建的容器的refcount的值为 1。当对一个变量使用unset函数时,这个变量所在的容器的refcount值将减去一,如图第4步所示。如果refcount的值少于1,Zend引 擎将翻译这个变量容器,如图第5步所示。
传递变量给函数(Passing Variables to Functions)
除了所有脚本共用的全局符号表以外,每个用户定义的函数在调用时都会创建一个属于自己的符号表,用来存放它自己的变量。当一个函数被调用后,Zend引擎 就会创建一个这样的符号表,当这个函数返回时这个函数表就会被释放。一个函数要么通过return语句返回,要么因为函数结束而返回(译者注:无返回的函 数默认会返回NULL)。如下图所示:
图3详细介绍了变量是如何传递给函数的。
第一步,我们将”thisis”赋给变量$a,然后我们将这个变量传递do_something()函数的$s变量。
第二步,你可以看到这与变量赋值的操作是一样的(与我们在前一小节提到的$b = $a类似),只是其存储在不同的符号表(函数符号表),并且引用计数加2,而不是加1。原因是函数栈也包含了这个变量容器的引用。
第三步,当我们赋新值给变量$s,原变量容器的refcount减1,并且创建一个包含了新值的变量容器。
第四步,我们通过return语句返回一个变量。返回的变量从全局符号表中获取一个实体并将其refcount的值增加1.当函数结束时,函数的符 号表将被销毁。在销毁的过程中,Zend引擎将遍历符号表中的每个变量,并将其refcount的值减少。当变量容器的refount的值变为0,这个变 量容器将会被销毁。如你所见,由于 PHP的引用计数机制,变量容器不是以拷贝的方式从函数返回。如果变量$s在第三步时没有被修改,则变量$a和$b将一直指向相同的变量容器(这个容器的 refcount为2)。在这种情况下,语句$a = “this is”将不会创建变量容器的副本。
英文原文地址:http://derickrethans.nl/files/phparch-php-variables-article.pdf
PHP变量在内存中的存储方式的更多相关文章
- <转载>浅谈C/C++的浮点数在内存中的存储方式
C/C++浮点数在内存中的存储方式 任何数据在内存中都是以二进制的形式存储的,例如一个short型数据1156,其二进制表示形式为00000100 10000100.则在Intel CPU架构的系统中 ...
- C语言中浮点数在内存中的存储方式
关于多字节数据类型在内存中的存储问题 //////////////////////////////////////////////////////////////// int ,short 各自是4. ...
- QList介绍(QList比QVector更快,这是由它们在内存中的存储方式决定的。QStringList是在QList的基础上针对字符串提供额外的函数。at()操作比操作符[]更快,因为它不需要深度复制)非常实用
FROM:http://apps.hi.baidu.com/share/detail/33517814 今天做项目时,需要用到QList来存储一组点.为此,我对QList类的说明进行了如下翻译. QL ...
- Java变量在内存中的存储
目录 Java变量在内存中的存储 成员变量 局部变量 总结 Java变量在内存中的存储 以下探究成员变量和局部变量在内存中的存储情况. package com.my.pac04; /** * @aut ...
- Float在内存中的存储方式及IEC61131处理
Float在内存中的存储方式及IEC61131处理 1,fp32(32bits float)类型数据在存储器中占用4Bytes存储,且遵循IEEE-754标准: 一个浮点数分三部分组成: 符号位s(1 ...
- 数据在内存中的存储方式( Big Endian和Little Endian的区别 )(x86系列则采用little endian方式存储数据)
https://www.cnblogs.com/renyuan/archive/2013/05/26/3099766.html 1.故事的起源 “endian”这个词出自<格列佛游记>.小 ...
- float和double在内存中的存储方式
本文转载于:http://wenku.baidu.com/link?url=ARfMiXVHCwCZJcqfA1gfeVkMOj9RkLlR9fIexbgs9gDdV8rIS48A1_xe1y6YgX ...
- C++成员函数在内存中的存储方式
用类去定义对象时,系统会为每一个对象分配存储空间.如果一个类包括了数据和函数,要分别为数据和函数的代码分配存储空间.按理说,如果用同一个类定义了10个对象,那么就需要分别为10个对象的数据和函数代码分 ...
- python中变量在内存中的存储与地址关系解析、浅度/深度copy、值传递、引用传递
---恢复内容开始--- 1.变量.地址 变量的实现方式有:引用语义.值语义 python语言中变量的实现方式就是引用语义,在变量里面保存的是值(对象)的引用(值所在处内存空间的地址).采用这种方式, ...
随机推荐
- MOTION-MATCHING IN UBISOFT’S FOR HONOR翻译
http://www.gameanim.com/2016/05/03/motion-matching-ubisofts-honor/ Introducing For Honor with a vide ...
- HDU 2068 RPG的错排
要求答对一半或以上就算过关,请问有多少组答案能使他顺利过关. 逆向思维,求答错一半或以下的组数 1,错排 错排公式的由来 pala提出的问题: 十本不同的书放在书架上.现重新摆放,使每本书都不在原来放 ...
- Linux系统MySQL开启远程连接
1.远程连接上Linux系统,确保Linux系统已经安装上了MySQL数据库.登陆数据库.mysql -uroot -p(密码). 2.创建用户用来远程连接 GRANT ALL PRIVILEGES ...
- ADO.NET Entity Framework
ADO.NET Entity Framework 是微软以 ADO.NET 为基础所发展出来的对象关系对应 (O/R Mapping) 解决方案, 早期被称为 ObjectSpace,现已经包含在 V ...
- Python list嵌套 三维数组
cores_multicast = [[] for i in xrange(64)] temp_list = [0, 1] temp_list2 = [0, 3] cores_multicast[0] ...
- Excel VBA自定义函数编写(UDF, User-Defined Function)
虽然知道Microsoft Office Excel可以支持用VB语言来进行复杂的编程和自定义函数的编写,但是一直以来都没有这个需求. 这次遇到的问题是要根据一列数组计算出一个值,但计算过程又比较复杂 ...
- [ASE]项目介绍及项目跟进——TANK BATTLE·INFINITE
童年的记忆,大概是每周末和小伙伴们围坐在电视机前,在20来寸的电视机屏幕里守卫着这个至今都不知道是什么的白色大鸟. 当年被打爆的坦克数量估计也能绕地球个三两圈了吧. 十几年过去了,游戏从2D-3D,画 ...
- 如何查看Android的Keystore文件的SHA1值
像使用百度地图api时候,一般需要获取keystore的SHA1值,这里就手把手教大家如何查看Android的keystore文件中的SHA1值. 第一步: 打开cmd,切换到keystore所在的文 ...
- Intellij IDEA Java web 项目搭建
Java web 项目搭建 简介 在上一节java web环境搭建中,我们配置了开发java web项目最基本的环境,现在我们将采用Spring MVC+Spring+Hibernate的架构搭建一个 ...
- Java虚拟机13:互斥同步、锁优化及synchronized和volatile
互斥同步 互斥同步(Mutual Exclusion & Synchronization)是常见的一种并发正确性保证手段.同步是指子啊多个线程并发访问共享数据时,保证共享数据在同一时刻只能被一 ...