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 相关文章推荐
Php部分常见问题总结
Oct 09 PHP
聊天室php&amp;mysql(一)
Oct 09 PHP
PHP入门学习的几个不错的实例代码
Jul 13 PHP
php下网站防IP攻击代码,超级实用
Oct 24 PHP
php木马webshell扫描器代码
Jan 25 PHP
php获取文件内容最后一行示例
Jan 09 PHP
PHP图片自动裁切应付不同尺寸的显示
Oct 16 PHP
PHP制作3D扇形统计图以及对图片进行缩放操作实例
Oct 23 PHP
PHP获取表单数据与HTML嵌入PHP脚本的实现
Feb 09 PHP
PHP面向对象之领域模型+数据映射器实例(分析)
Jun 21 PHP
Laravel实现ApiToken认证请求
Oct 14 PHP
PHP 对象接口简单实现方法示例
Apr 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
提问的智慧
2006/10/09 PHP
DEDE采集大师官方留后门的删除办法
2011/01/08 PHP
PHP中使用json数据格式定义字面量对象的方法
2014/08/20 PHP
PHP Imagick完美实现图片裁切、生成缩略图、添加水印
2016/02/22 PHP
php快速排序原理与实现方法分析
2016/05/26 PHP
PHP如何获取当前主机、域名、网址、路径、端口等参数
2017/06/09 PHP
PHP实现负载均衡下的session共用功能
2018/04/17 PHP
PHP实现简单的协程任务调度demo示例
2020/02/01 PHP
PHP实现长轮询消息实时推送功能代码实例讲解
2021/02/26 PHP
JQuery 前台切换网站的样式实现
2009/06/22 Javascript
使用node.js半年来总结的 10 条经验
2014/08/18 Javascript
JavaScript中合并数组的N种方法
2014/09/16 Javascript
输入框过滤非数字的js代码
2014/09/18 Javascript
AngularJS实用开发技巧(推荐)
2016/07/13 Javascript
js实现手机发送验证码功能
2017/03/13 Javascript
解决React Native端口号修改的方法
2017/07/28 Javascript
前端开发之便利店收银系统代码
2019/12/27 Javascript
vue 数据遍历筛选 过滤 排序的应用操作
2020/11/17 Javascript
Python使用cookielib模块操作cookie的实例教程
2016/07/12 Python
Python操作Excel之xlsx文件
2017/03/24 Python
Python递归函数 二分查找算法实现解析
2019/08/12 Python
Python 过滤错误log并导出的实例
2019/12/26 Python
OpenCV实现机器人对物体进行移动跟随的方法实例
2020/11/09 Python
HTML5单选框、复选框、下拉菜单、文本域的实现代码
2020/12/01 HTML / CSS
巴西化妆品商店:Lojas Rede
2019/07/26 全球购物
可靠的数据流传输TCP
2016/03/15 面试题
Linux内核产生并发的原因
2016/11/08 面试题
中西医专业毕业生职业规划书
2014/02/24 职场文书
经营理念口号
2014/06/21 职场文书
2014年残疾人工作总结
2014/12/06 职场文书
2014年青年教师工作总结
2014/12/17 职场文书
2015年班主任个人工作总结
2015/03/31 职场文书
八年级作文之我的母亲
2019/12/10 职场文书
python基于scrapy爬取京东笔记本电脑数据并进行简单处理和分析
2021/04/14 Python
pyqt5打包成exe可执行文件的方法
2021/05/14 Python
教你nginx跳转配置的四种方式
2022/07/07 Servers