变量与其它变量明确区别的, 下面我来给各位介绍 static 静态变量和属性方法及静态变量的引用与静态函数的用法, 各位有需要了解的同学可参考.
静态变量: 变量范围的另一个重要特性是静态变量 (static variable), 静态变量仅在局部函数域中存在, 但当程序执行离开此作用域时, 其值并不丢失, 看看下面的例子.
例子 7-4. 演示需要静态变量的例子, 代码如下:
- <?php
- function Test() {
- $a = 0;
- echo $a;
- $a++;
- }
- ?-->
本函数没什么用处, 因为每次调用时都会将 $a 的值设为 0 并输出 "0", 将变量加一的 $a++ 没有作用, 因为一旦退出本函数则变量 $a 就不存在了, 要写一个不会丢失本次计数值的计数函数, 要将变量 $a 定义为静态的.
例子 7-5. 使用静态变量的例子, 代码如下:
- <?php
- function Test() {
- static $a = 0;
- echo $a;
- $a++;
- }
- ?>
现在, 每次调用 Test() 函数都会输出 $a 的值并加一.
静态变量也提供了一种处理递归函数的方法, 递归函数是一种调用自己的函数, 写递归函数时要小心, 因为可能会无穷递归下去, 必须确保有充分的方法来中止递归, 一下这个简单的函数递归计数到 10, 使用静态变量 $count 来判断何时停止.
例子 7-6, 静态变量与递归函数, 代码如下:
- <?php
- function Test() {
- static $count = 0;
- $count++;
- echo $count;
- if ($count <10) {
- Test();
- }
- $count--;
- }
- ?>
注: 静态变量可以按照上面的例子声明, 如果在声明中用表达式的结果对其赋值会导致解析错误.
例子 7-7. 声明静态变量, 代码如下:
- <?php
- function foo() {
- static $int = 0; // correct
- static $int = 1 + 2; // wrong (as it is an expression)
- static $int = sqrt(121); // wrong (as it is an expression too)
- $int++;
- echo $int;
- }
- ?>
全局和静态变量的引用
在 Zend 引擎 1 代, 驱动了 PHP4, 对于变量的 static 和 global 定义是以 references 的方式实现的, 例如, 在一个函数域内部用 global 语句导入的一个真正的全局变量实际上是建立了一个到全局变量的引用, 这有可能导致预料之外的行为, 如以下例子所演示的, 代码如下:
- <?php
- function test_global_ref() {
- global $obj;
- $obj = & new stdclass;
- }
- function test_global_noref() {
- global $obj;
- $obj = new stdclass;
- }
- test_global_ref();
- var_dump($obj);
- test_global_noref();
- var_dump($obj);
- ?>
执行以上例子会导致如下输出, 代码如下:
- NULL
- object(stdClass)(0) {
- }
类似的行为也适用于 static 语句, 引用并不是静态地存储的, 代码如下:
- <?php
- function &get_instance_ref() {
- static $obj;
- echo "Static object:";
- var_dump($obj);
- if (!isset($obj)) {
- // 将一个引用赋值给静态变量
- $obj = & new stdclass;
- }
- $obj--->property++;
- return $obj;
- }
- function &get_instance_noref() {
- static $obj;
- echo "Static object:";
- var_dump($obj);
- if (!isset($obj)) {
- // 将一个对象赋值给静态变量
- $obj = new stdclass;
- }
- $obj->property++;
- return $obj;
- }
- $obj1 = get_instance_ref();
- $still_obj1 = get_instance_ref();
- echo "n";
- $obj2 = get_instance_noref();
- $still_obj2 = get_instance_noref();
- ?>
执行以上例子会导致如下输出:
- Static object: NULL
- Static object: NULL
- Static object: NULL
- Static object: object(stdClass)(1) {
- ["property"]=>
- int(1)
- }
上例演示了当把一个引用赋值给一个静态变量时, 第二次调用 &get_instance_ref() 函数时其值并没有被记住.
注:
1. 函数外部声明静态变量意义不大, 函数内部声明静态变量受限于作用域, 函数外部不能修改函数内部静态变量.
2. 引用变量, 也是变量, 只不过它的值是变量的内存地址.
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 也是二个不同的变量, 只不过他们都指向同一个地方.
来源: https://www.php1.cn/detail/php-aa2c2a3344.html