變量與其它變量明確區別的,下面我來給各位介紹 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也是二個不同的變量,只不過他們都指向同一個地方.
新聞熱點
疑難解答