<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>潘锦的空间 &#187; 引用</title>
	<atom:link href="https://www.phppan.com/tag/%e5%bc%95%e7%94%a8/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.phppan.com</link>
	<description>SaaS SaaS架构 团队管理 技术管理 技术架构 PHP 内核 扩展 项目管理</description>
	<lastBuildDate>Sun, 10 May 2026 02:26:45 +0000</lastBuildDate>
	<language>zh-CN</language>
		<sy:updatePeriod>hourly</sy:updatePeriod>
		<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=3.9.40</generator>
	<item>
		<title>深入理解PHP之引用一</title>
		<link>https://www.phppan.com/2011/03/phparch-php-variables-article-1/</link>
		<comments>https://www.phppan.com/2011/03/phparch-php-variables-article-1/#comments</comments>
		<pubDate>Tue, 08 Mar 2011 02:22:52 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[refcount]]></category>
		<category><![CDATA[变量]]></category>
		<category><![CDATA[引用]]></category>
		<category><![CDATA[引用计数]]></category>

		<guid isPermaLink="false">http://www.phppan.com/?p=1300</guid>
		<description><![CDATA[深入理解PHP之引用一 作者Derick Rethans 译者：Martin Pan&#60;http://ww [&#8230;]]]></description>
				<content:encoded><![CDATA[<p align="center"><strong>深入理解PHP之引用一</strong></p>
<p align="right">作者Derick Rethans</p>
<p align="right">译者：Martin Pan&lt;http://www.phppan.com/&gt;</p>
<p>PHP是弱语言，其变量处理的过程是不可见的。</p>
<p>你是否曾经很想知道在变量拷贝的时候，PHP引擎做了什么？</p>
<p>你是否曾经很想知道一个函数是如何以引用的方式返回一个变量？</p>
<p>如果是这样，请您接着向下看。</p>
<p>每门计算机语言都需要一些容器来保存变量数据。在一些语言当中，变量都有特定的类型，如字符串，数组，对象等等。比如C和Pascal就属于这种。而PHP则没有这样的类型。在PHP中，一个变量在某一行是字符串，可能到下一行就变成了数字。变量可以经常在不同的类型间轻易的转化，甚至是自动的转换。PHP之所以成为一个简单并且强大的语言，很大一部分的原因是它拥有弱类型的变量。但是有些时候这也会带来一些有趣的问题。</p>
<p>在PHP内部，变量是存储在一个叫做zval的容器中。它不仅仅包含变量的值，也包含变量的类型。Python和PHP类似，也有一个标签标记变量类型。变量容器中包含一些Zend引擎用来区分是否引用的字段。同时它也包含这个值的引用计数。</p>
<p>变量存储在一个相当于关联数组的符号表中。这个数组以变量名为key,并且指向包含了这些变量的容器。如图1所示：</p>
<p><a href="http://www.phppan.com/wp-content/uploads/2011/03/php-variables-01.png"><img class="aligncenter size-full wp-image-1302" title="php-variables-01" src="http://www.phppan.com/wp-content/uploads/2011/03/php-variables-01.png" alt="php-variables-01" width="756" height="410" /></a></p>
<h2>引用计数</h2>
<p align="left">PHP试着在变量拷贝(如 $a = $b )的时候变得聪明些。“=”也称为赋值操作符。当进行赋值操作时，Zend引擎不会创建一个新的变量窗口，而是增大变量窗口的 refcount 字段，你可以想象一下，当这个变量是一个巨大的字符串或一个巨大 的数组时，这将节约多少的内存。如图2所示，</p>
<p style="text-align: center;" align="left"><a href="http://www.phppan.com/wp-content/uploads/2011/03/php-variables-02.png"><img class="aligncenter size-full wp-image-1303" title="php-variables-02" src="http://www.phppan.com/wp-content/uploads/2011/03/php-variables-02.png" alt="php-variables-02" width="646" height="896" /></a></p>
<p>第一步： 变量a,包含文本”this is”。默认情况下，引用计数等于1</p>
<p align="left">第二步：将变量$a赋值给$b和$c。这里没有新的变量容器生成，仅仅是每次在变量赋值操作时将refcount加1。因为这里执行了两次赋值操作，所以refcount最后会变成3。</p>
<p align="left">现在，也许你很想知道当变量$c改变时将发生什么。根据refcount的值的不同，它会有两种不同的处理方式。如果refcount等于1，这个变量容器将更新它的值（也许同时会更新它的类型）。如果refcount大于1，将创建一个包含了新值（和类型）的变量容器。如图2所示的第三步，$a变量所在的变量容器的refcount值被减去一，现在refcount的值是2，而新创建的容器的refcount的值为1。当对一个变量使用unset函数时，这个变量所在的容器的refcount值将减去一，如图第4步所示。如果refcount的值少于1，Zend引擎将翻译这个变量容器，如图第5步所示。</p>
<p align="left">
<h2>传递变量给函数（Passing Variables to Functions）</h2>
<p align="left">除了所有脚本共用的全局符号表以外，每个用户定义的函数在调用时都会创建一个属于自己的符号表，用来存放它自己的变量。当一个函数被调用后，Zend引擎就会创建一个这样的符号表，当这个函数返回时这个函数表就会被释放。一个函数要么通过return语句返回，要么因为函数结束而返回(译者注：无返回的函数默认会返回NULL)。如图3所示：</p>
<p align="left">
<p style="text-align: center;" align="left"><a href="http://www.phppan.com/wp-content/uploads/2011/03/php-variables-03.png"><img class="aligncenter size-large wp-image-1304" title="php-variables-03" src="http://www.phppan.com/wp-content/uploads/2011/03/php-variables-03-1024x684.png" alt="php-variables-03" width="717" height="479" /></a></p>
<p align="left">图3详细介绍了变量是如何传递给函数的。</p>
<p align="left">第一步,我们将”thisis”赋给变量$a，然后我们将这个变量传递do_something()函数的$s变量。</p>
<p align="left">第二步，你可以看到这与变量赋值的操作是一样的（与我们在前一小节提到的$b = $a类似），只是其存储在不同的符号表（函数符号表），并且引用计数加2，而不是加1。原因是函数栈也包含了这个变量容器的引用。</p>
<p align="left">第三步，当我们赋新值给变量$s，原变量容器的refcount减1，并且创建一个包含了新值的变量容器。</p>
<p>第四步，我们通过return语句返回一个变量。返回的变量从全局符号表中获取一个实体并将其refcount的值增加1.当函数结束时，函数的符号表将被销毁。在销毁的过程中，Zend引擎将遍历符号表中的每个变量，并将其refcount的值减少。当变量容器的refount的值变为0,这个变量容器将会被销毁。如你所见，由于 PHP的引用计数机制，变量容器不是以拷贝的方式从函数返回。如果变量$s在第三步时没有被修改，则变量$a和$b将一直指向相同的变量容器（这个容器的refcount为2）。在这种情况下，语句$a = “this is”将不会创建变量容器的副本。</p>
<p>英文原文地址：http://derickrethans.nl/files/phparch-php-variables-article.pdf</p>
<p>以上只是第一部分的内容，原来看懂很容易，翻译出来相当难。</p>
]]></content:encoded>
			<wfw:commentRss>https://www.phppan.com/2011/03/phparch-php-variables-article-1/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
