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来处理多个提交任务
Oct 09 PHP
PHP 数组实例说明
Aug 18 PHP
简单PHP上传图片、删除图片实现代码
May 12 PHP
Apache 配置详解(最好的APACHE配置教程)
Jul 04 PHP
PHP连接SQLServer2005的实现方法(附ntwdblib.dll下载)
Jul 02 PHP
php简单定时执行任务的实现方法
Feb 23 PHP
php实现ip白名单黑名单功能
Mar 12 PHP
调试WordPress中定时任务的相关PHP脚本示例
Dec 10 PHP
WordPress中给文章添加自定义字段及后台编辑功能区域
Dec 19 PHP
WordPress特定文章对搜索引擎隐藏或只允许搜索引擎查看
Dec 31 PHP
Linux安装配置php环境的方法
Jan 14 PHP
Laravel如何创建服务器提供者实例代码
Apr 15 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
常见php数据文件缓存类汇总
2014/12/05 PHP
PHP回溯法解决0-1背包问题实例分析
2015/03/23 PHP
ThinkPHP中order()使用方法详解
2016/04/19 PHP
jquery入门——事件机制之事件中的冒泡现象示例解释
2020/09/12 Javascript
JavaScript中提前声明变量或函数例子
2014/11/12 Javascript
JavaScript与HTML的结合方法详解
2015/11/23 Javascript
JS实现简单的二维矩阵乘积运算
2016/01/26 Javascript
Bootstrap3 input输入框插入glyphicon图标的方法
2016/05/16 Javascript
原生javascript实现的ajax异步封装功能示例
2016/11/03 Javascript
DOM 事件的深入浅出(二)
2016/12/05 Javascript
BootStrap table删除指定行的注意事项(笔记整理)
2017/02/05 Javascript
JavaScript中三种常见的排序方法
2017/02/24 Javascript
Vue.js 单页面多路由区域操作的实例详解
2017/07/17 Javascript
用最少的JS代码写出贪吃蛇游戏
2018/01/12 Javascript
Node.js爬取豆瓣数据实例分析
2018/03/05 Javascript
vue拖拽组件使用方法详解
2018/12/01 Javascript
Vue唯一可以更改vuex实例中state数据状态的属性对象Mutation的讲解
2019/01/18 Javascript
微信小程序tabBar设置实例解析
2019/11/14 Javascript
Vue 实现登录界面验证码功能
2020/01/03 Javascript
node.js中stream流中可读流和可写流的实现与使用方法实例分析
2020/02/13 Javascript
微信小程序scroll-view点击项自动居中效果的实现
2020/03/25 Javascript
简单谈谈Python中的闭包
2016/11/30 Python
详解python tkinter教程-事件绑定
2019/03/28 Python
利用pyinstaller打包exe文件的基本教程
2019/05/02 Python
python爬虫可以爬什么
2020/06/16 Python
HTML5自定义属性前缀data-及dataset的使用方法(html5 新特性)
2017/08/24 HTML / CSS
SQL里面IN比较快还是EXISTS比较快
2012/07/19 面试题
四种会话跟踪技术
2015/05/20 面试题
《神奇的克隆》教学反思
2014/04/10 职场文书
幼儿园辞职信范文
2015/02/27 职场文书
2015秋季开学演讲稿范文
2015/07/16 职场文书
2016年五四青年节校园广播稿
2015/12/17 职场文书
承诺书怎么写 ?
2019/04/16 职场文书
七年级作文之游记
2019/12/11 职场文书
pytorch加载预训练模型与自己模型不匹配的解决方案
2021/05/13 Python
Win10 heic文件怎么打开 ? Win10 heic文件打开教程
2022/04/06 数码科技