PHP中$GLOBALS变量、global关键字、函数中static关键字详解

2012-9-13 雨寒 Php

在了解PHP变量之前, 我们先看下段式内存管理架构的内存段的划分。通常操作系统会将物理内存划分为以下几个逻辑段:

    1.Text-Segment,这个段最大的特点就是只读。一般存放可执行代码,也有可能常量也存放在这里,比如字符串常量

    2.BSS-Segment,这里存放了那些没有初始化的变量。某种意义来讲,没有初始化的变量都是垃圾,不可用

    3.Data-Segment,这里存放了全局变量和静态变量,直到脚本运行结束,操作系统才会回收这里的内存空间,变量亦会被销毁。

    4.Stack-Heap Segment 函数参数与本地变量(也称局部变量)存放在堆中(stack),还有返回值等等。

作为PHP程序而言,我们关心的是全局变量、静态变量、局部变量、函数参数以及函数返回值。局部变量和函数参数基本山是一样,在初始化的时候分配分配内存空间,推出函数后操作系统会收回内存空间。而全局变量与静态变量要到PHP运行结束后,内存才会释放空间。与全局变量不同,所有静态变量在程序执行之前就初始化并分配了内存空间。

注:
1.函数外部声明静态变量意义不大,函数内部声明静态变量受限于作用域,函数外部不能修改函数内部静态变量。
2.引用变量,也是变量,只不过它的值是变量的内存地址。

php保留字 global和$GLOBALS
 很多人都认为global和$GLOBALS只是写法上的差别,其实不然。根据官方的解释是:

1.$GLOBALS['var']是外部的全局变量本身。

2.global $var 是外部全局变量$var的同名引用或者指针。

举例说明一下:

<?php
$var1 = 1;
$var2 = 2;
function example1() {
    $GLOBALS['var2'] = & $GLOBALS['var1'];
}
example1();
echo $var2;
?>正常打印结果为:1
 <?php
$var1 = 1;
$var2 = 2;
function example2() {
    global $var1,$var2;
    $var2 = &$var1;
}
example2();
echo $var2;
?>
正常打印结果为2
原因:函数内部$var2的引用指向了$var1的引用地址。导致实质的值没有改变。
php保留字 global和static
<?php $i = $j = 8; function global_var() {    global $j, $b;    $c = $j = $b = $i = 4; } global_var(); echo "i:$i, j:$j b:$b c:$c \n"; //i:8, j:4 b:4 c: ?>
函数外和内都有变量$i,但是他们二个是完全不同的变量。函数外的$i是全局变量,该内存空间直到脚本运行结束后才会被释放。函数内的$i是局部变量,程序流经过函数的时候,初始化,退出函数的时候,内存被系统回收,再次调用函数,则再次分配内存空间和回收内存空间。二次分配的内存空间有可能是同一内存地址,也有可能不能同一内存地址。
与$i不同的是$j,通过关键字global将局部变量”转为”全局变量。当调用函数global_var()的时候,并不会重新给$j分配内存空间。同样的,可以在函数外打印$b,却不能打印$c是因为$b是全局变量,不会被销毁。而$c则不能打印,$c已经不存在了,在退出函数就给销毁了。

<?php $a = 2; static $b = 2; static $c = 3; function global_var() {     static $i, $c;     global $j, $a;     $c = $a = $b = $i = $j = 4; } global_var(); echo "a:$a b:$b c:$c i:$i j:$j"; //a:4 b:2 c:3 i: j:4 ?>
首先,我们看函数外的$b和$c,即是全局变量又是static变量。这里static修饰没有太大的意义,因为他们都存放在数据段(data-segment),直到脚本运行完了之后才会被回收。然后,我们再看函数里面的$i和$c,函数调用后,$i和$c其实都没有被回收,但是$i输出是NULL和$c输出是3,这是因为他们的作用域是函数内部,不是函数外部,也就是说$i和$c在函数外是不可见的。函数内static变量的意义就在于此:仅函数内部可见且不会被销毁。也就是说,保证函退出函数,变量也不会被回收,但又不会被其它函数修改。(注:函数外和函数内的$c是二个不同的变量)

<?php function global_var() {    static $i;    ++$j;    ++$i;    echo "j:$j i:$i \n"; } global_var(); //j:1 i:1  global_var();  //j:1 i:2 global_var();  //j:1 i:3 ?>
上例中,变量$j一直都是1,而$i每调用一次就累加1。这是因为,局部变量存放在堆段,每次退出函数时都会被回收。而$i存放在存放在数据段(data-segment),直到程序执行完毕才会被回收。我们平常说的static变量,如果没有特别指明,都说的是函数内部的static变量。

引用函数与static变量
既然static变量要直到脚本执行结束,才会被销毁。那么,有没有办法访问该变量的值呢?我们来看看下面的示例:

<?php get_local_static_var(); $ptr = &get_local_static_var(); get_local_static_var(); ++$ptr; get_local_static_var(); what_i($ptr); get_local_static_var();  //?? what_p($ptr); get_local_static_var();  //??  function &get_local_static_var() {     static $i;     ++$i;     echo "i:$i \n";     return $i; }  function what_i($ptr) {    $i = &get_local_static_var();    ++$i;    ++$ptr; }  function what_p(&$ptr) {    $i = &get_local_static_var();    ++$i;    ++$ptr; } ?>
二个凝问号处,分别输出是8和12。这就说明了只要变量没有被销毁,还是可以被访问。我们可以通过引用函数将static变量的地址返回其它函数。其它函数则可通过static变量的地址访问并且修改它的值。
上例第一处??,为什么是8,而不是9。这是因为what_i($ptr)函数,要求参数是按值传递,即此处的$ptr实参值是5,且参数$ptr和全局变量$ptr是二个不同的变量。第二处??的值是12,为什么不是11的道理亦是如此。what_p(&$ptr)函数,要求参数是按引用传递,即此处的$ptr是指向static变量$i的地址,需要注意的是参数$ptr和全局变量$ptr也是二个不同的变量,只不过他们都指向同一个地方。

 

参考:http://www.perfgeeks.com/?p=589

标签: PHP global static

Powered by emlog 沪ICP备2023034538号-1