PHP中变量引用与变量销毁机制分析


Posted in PHP onNovember 15, 2014

本文实例分析了PHP中变量引用与变量销毁机制。分享给大家供大家参考。具体分析如下:

变量是php中一个非常重要的类型了,我们的有数据都通过变量或常量来进行操作,下文来看看变量引用与变量销毁。

在php中,符号"&"表示引用。

1、看看不引用的情况是这样子:

$a  = "hello world";//定义一个变量,下面赋值给$b

$b = $a;//这一步没有在$a之前加符号&,像这样子"$b= & $a"。没有加&,实际上原理是会将变量$a复制拷贝一份,也就是内存中重新申请一个地址存储变量$b了

ps:在php中,使用"="直接赋值,其实就是拷贝一份右边的变量给b,会生成一份内存空间,结果可能是同样的内容在内存中两份。在有些关于php性能方面提到,这样子会多占有内存空间。不过我接触中,大部分人没怎么注意,其实一般应用这样子用产生的显著差异并不明显。不会看到什么效果,其实我本人也没经常使用&进行引用,呵呵。只是我觉得,深入了解里面的实现原理,非常有必要。我喜欢关注原理性的东西。

2、使用符号&进行引用

$a  = "hello world";

$b = &$a;

使用引用,php引擎不会拷贝一份变量,其实就是将指针指向了$a在内存中的地址,$b中就是保存了这个指针。
所以使用引用的时候,把$b的值改变,$a也会跟着改变
比如:
$a  = "hello world";

$b = &$a;

$b = "test new value";//把b的值改掉,a的值也会跟着改变

echo $a;//输出test new value,因为改变了b的值也会改变a的值。

经常在定义函数的时候看到像这样的情况:

function test (& $param)

{

//函数定义的内容

$param++;

}

解释:$param前面带有引用,所以传入进来的参数并不会在内存中拷贝一份,而是直接对原来的内存空间进行引用。所以:如果里对使用符号&传入进来的变量值进行修改了,那么也会改变原来的内存空间中的值。
做个测验如下:
$k = 8;

test($k);

echo $k;//结果$k的值被函数里面改变了,输出9。

还会经常看到这样子调用函数:
$return  = & test_func();

前面了解到php引擎的机制是:=会把右边的内容拷贝一份给予左边的变量。所以使用&就是将函数的结果不会进行拷贝一份,实际上我的理解是把指针给了左边的变量。
什么是指针,以前学c语言中的概念。我的理解是就是:指针,指针,指向针(指南针,呵呵)。把指针看成是一个内存的地址容易理解点,计算机就知道去内存什么位置找数据了吧。这是浅显的理解,深入的我不会,呵呵。

总结:使用引用是为了减少内存资源的占用。

php手册中对引用的解释如下:

在 PHP 中引用意味着用不同的名字访问同一个变量内容。这并不像 C 的指针,替代的是,引用是符号表别名。注意在 PHP 中,变量名和变量内容是不一样的,因此同样的内容可以有不同的名字。最接近的比喻是 Unix 的文件名和文件本身——变量名是目录条目,而变量内容则是文件本身。引用可以被看作是 Unix 文件系统中的 hardlink。

3、销毁变量的时候。并不会改变原来的值。

试验:$b = & $a;
既然改变$b的值,$a的值也跟着改变,假如把$b销毁掉(内存中不占用空间了,不是null,也不是值为""),$a的值是不是也会跟着被删掉呢?

其实国外有本php方面的书中专门提到了这个机制。2年前看的。不是很记得了。原则是就是删除变量的时候,会自动拷贝。

其实这样子,就是为了避免把$b给删掉,造成把$a也给删掉的问题。

<?php

$a = 'd';

$b = & $a;

$b = 8;//因为是引用了,所以把b的值改掉,a的值也跟着改为8了。

var_dump($b,$a);

unset($b);//调用unset删除b变量,a变量不会删除

var_dump($b,$a);//输出null和8

调用unset删除$b变量的时候,php引擎从变量符号表中发现:我要删除的变量$b原来是引用了变量$a,这不好删除啊,因为一删除导致$a变量也没了,所以就先把$a变量拷贝一份后在删除$b变量。
关于php符号表:其实我的理解是,运行中所有变量名称都记录在里面,php来维护,具体的数据当然是存储在内存中,php就是根据这个符号表去回收没有用到的变量空间的,释放内存空间)。去看看php的垃圾回收机制(释放不再使用的内存空间),就是根据符号表进行的。
例子
<?php

$long="big_long_variable_name";

$$long="PHP";     /* 用存放在变量$long里的字符串作为新变量的变量名,等同于$big_long_variable_name="PHP"; */

$short=& $big_long_variable_name;  /* 取变量$big_long_variable_name的值赋给变量$short,此时$short的值为"PHP",等同于$short=& $$long; */

print "01 /$short is $short.";   /* "/$"是转义序列,表示输出一个美元符号$,下同。本语句的作用是输出:01 $short is PHP. */

print "02 Long is $big_long_variable_name."; /* 输出:02 Long is PHP. */

?>

<br />

<br />

<?php

$big_long_variable_name.=" rocks!"; /* 重新对$big_long_variable_name赋值。重新赋值过程中,由于在$big_long_variable_name的后面添加了.(点号),因而变量$big_long_variable_name此时的值应为原值("PHP")+新值(" rocks!"),即变量$big_long_variable_name当前完整的值为"PHP rocks!"。下同。*/

print "03 /$short is $short";   /* 输出:03 $short is PHP rocks! */

print "04 Long is $big_long_variable_name"; /* 输出:04 Long is PHP rocks! */

?>

<br />

<br />

05 $short is PHP rocks!

06 Long is PHP rocks!

<br />

<br />

<?php

$short.="Programming $short";   /* 重新对变量$short赋值。由于在$short后面添加了.(点号),因此请参考上例分析$short的值。*/

print "07 /$short is $short";   /* 输出:07 $short is PHP rocks!Programming PHP rocks! */

print "08 Long is $big_long_variable_name"; /* 由于变量$short被重新赋值为Programming PHP rocks!,因而变量$big_long_variable_name的值也与$short一同被改变为"PHP rocks!Programming PHP rocks!"。本语句输出:08 Long is PHP rocks!Programming PHP rocks!注意,如果是对具有相同值的一个变量进行销毁unset( ),则另一个变量不适用于此种情况,即不会随之被一同销毁。*/

?>

<br />

<br />

09 $short is Programming PHP rocks!

10 Long is Programming PHP rocks!

<br />

<br />

<?php

$big_long_variable_name.="Web Programming $short";  /* 变量$big_long_variable_name被重新赋值,此时它完整的值应为PHP rocks!Programming PHP rocks!Web Programming PHP rocks!Programming PHP rocks!。变量$short的值此时与变量$big_long_variable_name一致。请分别参考第5处、第10处注释进行分析。*/

print "11 /$short is $short";     /* 输出:11 PHP rocks!Programming PHP rocks!Web Programming PHP rocks!Programming PHP rocks! */

print "12 Long is $big_long_variable_name";

?>

<br />

<br />

<?php

unset($big_long_variable_name);   /* 用unset( )销毁变量$big_long_variable_name,变量$short不会因此受到任何影响。*/

print "13 /$short is $short";   /* 虽然销毁了变量$big_long_variable_name,但$short没有受到影响,它的值仍是最近一次被赋予的PHP rocks!Programming PHP rocks!Web Programming PHP rocks!Programming PHP rocks! */

print "14 Long is $big_long_variable_name."; /* 变量$big_long_variable_name已被销毁,故而无值。输出:14 Long is. */

snow;                                    

?>

<br />

<br />

<?php $short="No point TEST1";   /* 重新对变量$short赋值。由于这次没有在$short后面添加.(点号),因此$short当前的值为"No point TEST1"。*/

print "15 /$short is $short.";   /* 输出:15 $short is No point TEST1. */

$short="No point TEST2 $short";   /* 重新对变量$short赋值。没在$short的后面添加.(点号),但引用了它自身最近一次的值"No point TEST1"。*/

print "16 /$short is $short.";   /* 输出:16 $short is No point TEST2 No point TEST1. */

希望本文所述对大家的php程序设计有所帮助。

PHP 相关文章推荐
Apache, PHP在Windows 9x/NT下的安装与配置 (二)
Oct 09 PHP
php 格式化数字的时候注意数字的范围
Apr 13 PHP
PHP spl_autoload_register实现自动加载研究
Dec 06 PHP
php xml常用函数的集合(比较详细)
Jun 06 PHP
windows7下安装php的imagick和imagemagick扩展教程
Jul 04 PHP
Yii框架在页面输出执行sql语句以方便调试的实现方法
Dec 24 PHP
推荐一本PHP程序猿都应该拜读的书
Dec 31 PHP
php+mysql实现简单的增删改查功能
Jul 13 PHP
Redis构建分布式锁
Mar 28 PHP
PHP魔术方法之__call与__callStatic使用方法
Jul 23 PHP
Laravel框架创建路由的方法详解
Sep 04 PHP
php抽象方法和普通方法的区别点总结
Oct 13 PHP
微信公众号开发之微信公共平台消息回复类实例
Nov 14 #PHP
微信公众号点击菜单即可打开并登录微站的实现方法
Nov 14 #PHP
php异步多线程swoole用法实例
Nov 14 #PHP
PHP判断数据库中的记录是否存在的方法
Nov 14 #PHP
PHP合并静态文件详解
Nov 14 #PHP
php判断类是否存在函数class_exists用法分析
Nov 14 #PHP
php中常量DIRECTORY_SEPARATOR用法深入分析
Nov 14 #PHP
You might like
Zerg兵种介绍
2020/03/14 星际争霸
PHP编程最快明白(第一讲 软件环境和准备工作)
2010/10/25 PHP
PHP spl_autoload_register实现自动加载研究
2011/12/06 PHP
PHP函数spl_autoload_register()用法和__autoload()介绍
2012/02/04 PHP
php多文件上传功能实现原理及代码
2013/04/18 PHP
解析php中session的实现原理以及大网站应用应注意的问题
2013/06/17 PHP
php中session_id()函数详细介绍,会话id生成过程及session id长度
2015/09/23 PHP
非常好的js代码
2006/06/27 Javascript
对YUI扩展的Gird组件 Part-2
2007/03/10 Javascript
复制Input内容的js代码_支持所有浏览器,修正了Firefox3.5以上的问题
2010/06/21 Javascript
你需要知道的10个最佳javascript开发实践小结
2012/04/15 Javascript
Vue概念及常见命令介绍(1)
2016/12/08 Javascript
javascript编程开发中取色器及封装$函数用法示例
2017/08/09 Javascript
vue 设置路由的登录权限的方法
2018/07/03 Javascript
React 组件中的 bind(this)示例代码
2018/09/16 Javascript
Egg.js 中 AJax 上传文件获取参数的方法
2018/10/10 Javascript
JS检索下拉列表框中被选项目的索引号(selectedIndex)
2019/12/17 Javascript
原生js+canvas实现贪吃蛇效果
2020/08/02 Javascript
python访问sqlserver示例
2014/02/10 Python
Python中的二叉树查找算法模块使用指南
2014/07/04 Python
python将MongoDB里的ObjectId转换为时间戳的方法
2015/03/13 Python
Python2.x中文乱码问题解决方法
2015/06/02 Python
Python实现字典的key和values的交换
2015/08/04 Python
python检查URL是否正常访问的小技巧
2017/02/25 Python
python多进程实现进程间通信实例
2017/11/24 Python
浅谈python3发送post请求参数为空的情况
2018/12/28 Python
详解如何在pyqt中通过OpenCV实现对窗口的透视变换
2020/09/20 Python
CSS3效果:自定义“W”形运行轨迹实例
2017/03/29 HTML / CSS
荷兰电脑专场:Paradigit
2018/05/05 全球购物
NET程序员上机面试题
2015/05/23 面试题
即兴演讲稿
2014/01/04 职场文书
蛋糕店的商业计划书范文
2014/01/27 职场文书
致标枪运动员广播稿
2014/02/06 职场文书
新闻学专业职业生涯规划范文:我的人生我做主
2014/09/12 职场文书
冰峪沟导游词
2015/02/09 职场文书
Netflix《海贼王》真人版剧集多张片场照曝光
2022/04/04 日漫