PHP语言中global和$GLOBALS[]的分析 之二


Posted in PHP onFebruary 02, 2012

还是借用上一篇的例子:

PHP代码

<?php 
// 例子1 
function test_global() { 
global $var1, $var2; 
$var2 =& $var1; 
} 
function test_globals() { 
$GLOBALS['var3'] =& $GLOBALS['var1']; 
} 
$var1 = 5; 
$var2 = $var3 = 0; 
test_global(); 
print $var2 .”\n”; 
test_globals(); 
print $var3 .”\n”; 
?>

执行结果为:
0
5
怎么会这样呢?不应该是2个5吗?怎么会出现1个0和1个5呢?

恩,我们保留以上问题,深入分析$GLOBALS和global的原理!
我们都知道变量其实是相应物理内存在代码中的”代号”而已
引用php手册的$GLOBALS的解释:
Global 变量:$GLOBALS,注意: $GLOBALS 在 PHP 3.0.0 及以后版本中适用。
由所有已定义全局变量组成的数组。变量名就是该数组的索引。这是一个“superglobal”,或者可以描述为自动全局变量。
也就是说上面代码中的$var1和$GLOBALS['var1']是指的同一变量,而不是2个不同的变量!
下面来分析global到底做了什么?
引用php手册的global的解释:
如果在一个函数内部给一个声明为 global 的变量赋于一个引用,该引用只在函数内部可见。可以通过使用 $GLOBALS 数组避免这一点。
我们都知道php中的函数所产生的变量都是函数的私有变量,那么global关键字产生的变量也肯定逃不出这个规则,为什么这么说呢,看下面的代码:
PHP代码

<?php 
// 例子2 
function test() { 
global $a; 
unset($a); 
} 
$a = 1; 
test(); 
print $a; 
?>

执行结果为:
1
为什么会输出1呢?不是已经把$a给unset了吗?unset失灵了?php的bug?
都不是,其实unset起作用了,是把test函数中的$a给unset掉了,可以在函数test()中加入
print $a;
来测试!
接着回到上面的例子1,看test_global中的这一代码“$var2 =& $var1;”,上面是一个引用赋值运算,也就是$var2将指向var1所指向的物理内存地址,所以例子1执行过test_global函数以后,变量的变化只在函数的局部产生效应,在函数外部$var2的指向物理内存地址并没有变化,还是它自己.
此时,就能理解为什么例子1执行完以后,$var2是0,而$var3是5了!
所以我们得出一个结论,在函数中global和$GLOBALS[]的区别在于:
global在函数产生一个指向函数外部变量的别名变量,而不是真正的函数外部变量,一但改变了别名变量的指向地址,就会发生一些意料不到情况,例如例子 1.
$GLOBALS[]确确实实调用是外部的变量,函数内外会始终保持一致
可以对照 下面两个列子再加深下印象:
global:
<?php 
function myfunction(){ 
global $bar; 
unset($bar); 
} 
$bar=”someting”; 
myfunction(); 
echo $bar; 
?>

输出:someting
$GLOBALS[]:
<?php 
function foo() 
{ 
unset($GLOBALS['bar']); 
} 
$bar = “something”; 
foo(); 
echo $bar; 
?>

输出:空
当按照上面的思路理解后,碰到下面的情况是不是又有些晕呢?
<?php 
$a = 1; 
$b = 2; 
function Sum() 
{ 
global $a, $b; 
$b = $a + $b; 
} 
Sum(); 
echo $b; 
?>

输出将是 “3″。在函数中申明 了全局变量 $a 和 $b,任何变量的所有引用变量都会指向到全局变量。
怎么不是2呢,在函数外部不是不影响吗,请注意$b在函数中并没有通过引用修改,而是修改的$b指向物理内存的值,因此外部输入为3。
PHP 相关文章推荐
默默小谈PHP&amp;MYSQL分页原理及实现
Jan 02 PHP
php addslashes和mysql_real_escape_string
Jan 24 PHP
php写的简易聊天室代码
Jun 04 PHP
关于JSON以及JSON在PHP中的应用技巧
Nov 27 PHP
ThinkPHP实例化模型的四种方法概述
Aug 22 PHP
php中字符集转换iconv函数使用总结
Oct 11 PHP
10款PHP开源商城系统汇总介绍
Jul 23 PHP
thinkPHP删除前弹出确认框的简单实现方法
May 16 PHP
PHP实践教程之过滤、验证、转义与密码详解
Jul 24 PHP
PHP二维数组实现去除重复项的方法【保留各个键值】
Dec 21 PHP
vmware linux系统安装最新的php7图解
Apr 14 PHP
PHP设计模式之装饰器(装饰者)模式(Decorator)入门与应用详解
Dec 13 PHP
php中global和$GLOBALS[]的分析之一
Feb 02 #PHP
PHP开发者常犯的10个MySQL错误更正剖析
Jan 30 #PHP
PHP中全面阻止SQL注入式攻击分析小结
Jan 30 #PHP
几种有用的变型 PHP中循环语句的用法介绍
Jan 30 #PHP
通过PHP修改Linux或Unix口令的方法分享
Jan 30 #PHP
php代码收集表单内容并写入文件的代码
Jan 29 #PHP
php 无法加载mysql的module的时候的配置的解决方案引发的思考
Jan 27 #PHP
You might like
《APMServ 5.1.2》使用图解
2006/10/23 PHP
php strtotime 函数UNIX时间戳
2009/01/14 PHP
PHP 变量的定义方法
2010/01/26 PHP
深入理解ob_flush和flush的区别(ob_flush()与flush()使用方法)
2013/02/06 PHP
如何在Ubuntu下启动Apache的Rewrite功能
2013/07/05 PHP
WordPress中制作导航菜单的PHP核心方法讲解
2015/12/11 PHP
浅谈PHP中如何实现Hook机制
2017/11/14 PHP
Javascript中valueOf与toString区别浅析
2013/03/19 Javascript
javascript给span标签赋值的方法
2015/11/26 Javascript
jQuery新窗口打开外链接
2016/07/21 Javascript
Javascript农历与公历相互转换的简单实例
2016/10/09 Javascript
浅谈JavaScript中promise的使用
2017/01/11 Javascript
浅谈Vue-cli单文件组件引入less,sass,css样式的不同方法
2018/03/13 Javascript
vue地区选择组件教程详解
2018/05/04 Javascript
JS字典Dictionary类定义与用法示例
2019/02/01 Javascript
js实现简单分页导航栏效果
2019/06/28 Javascript
layUI实现三级导航菜单效果
2019/07/26 Javascript
python实现的登录和操作开心网脚本分享
2014/07/09 Python
解决Python中由于logging模块误用导致的内存泄露
2015/04/23 Python
python关键字and和or用法实例
2015/05/28 Python
python基于multiprocessing的多进程创建方法
2015/06/04 Python
python实现彩色图转换成灰度图
2019/01/15 Python
Python处理时间日期坐标轴过程详解
2019/06/25 Python
django做form表单的数据验证过程详解
2019/07/26 Python
python实现简易淘宝购物
2019/11/22 Python
解决python gdal投影坐标系转换的问题
2020/01/17 Python
如何使用Python发送HTML格式的邮件
2020/02/11 Python
keras读取h5文件load_weights、load代码操作
2020/06/12 Python
HTML5单选框、复选框、下拉菜单、文本域的实现代码
2020/12/01 HTML / CSS
英国顶级家庭折扣店:The Works
2017/09/06 全球购物
新西兰网上购物,折扣店:BestDeals.co.nz
2019/03/20 全球购物
缓刑人员的思想汇报
2014/01/11 职场文书
医学生自我评价
2014/01/27 职场文书
二审代理词范文
2015/05/25 职场文书
通知怎么写?
2019/04/17 职场文书
七年级作文之游记
2019/12/11 职场文书