變量與其它變量明確區(qū)別的,下面我來給各位介紹 static 靜態(tài)變量和屬性方法及靜態(tài)變量的引用與靜態(tài)函數(shù)的用法,各位有需要了解的同學(xué)可參考.
靜態(tài)變量:變量范圍的另一個重要特性是靜態(tài)變量(static variable),靜態(tài)變量僅在局部函數(shù)域中存在,但當(dāng)程序執(zhí)行離開此作用域時,其值并不丟失,看看下面的例子.
例子 7-4.演示需要靜態(tài)變量的例子,代碼如下:
- <?php
- function Test ()
- {
- $a = 0;
- echo $a;
- $a++;
- }
- ?>
本函數(shù)沒什么用處,因為每次調(diào)用時都會將 $a 的值設(shè)為 0 并輸出 "0",將變量加一的 $a++ 沒有作用,因為一旦退出本函數(shù)則變量 $a 就不存在了,要寫一個不會丟失本次計數(shù)值的計數(shù)函數(shù),要將變量 $a 定義為靜態(tài)的.
例子 7-5. 使用靜態(tài)變量的例子,代碼如下:
- <?php
- function Test()
- {
- static $a = 0;
- echo $a;
- $a++;
- }
- ?>
現(xiàn)在,每次調(diào)用 Test() 函數(shù)都會輸出 $a 的值并加一.
靜態(tài)變量也提供了一種處理遞歸函數(shù)的方法,遞歸函數(shù)是一種調(diào)用自己的函數(shù),寫遞歸函數(shù)時要小心,因為可能會無窮遞歸下去,必須確保有充分的方法來中止遞歸,一下這個簡單的函數(shù)遞歸計數(shù)到 10,使用靜態(tài)變量 $count 來判斷何時停止.
例子 7-6,靜態(tài)變量與遞歸函數(shù),代碼如下:
- <?php
- function Test()
- {
- static $count = 0;
- $count++;
- echo $count;
- if ($count < 10) {
- Test ();
- }
- $count--;
- }
- ?>
注:靜態(tài)變量可以按照上面的例子聲明,如果在聲明中用表達式的結(jié)果對其賦值會導(dǎo)致解析錯誤.
例子 7-7.聲明靜態(tài)變量,代碼如下:
- <?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;
- }
- ?>
全局和靜態(tài)變量的引用
在 Zend 引擎 1 代,驅(qū)動了 PHP4,對于變量的 static 和 global 定義是以 references 的方式實現(xiàn)的,例如,在一個函數(shù)域內(nèi)部用 global 語句導(dǎo)入的一個真正的全局變量實際上是建立了一個到全局變量的引用,這有可能導(dǎo)致預(yù)料之外的行為,如以下例子所演示的,代碼如下:
- <?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);
- ?>
執(zhí)行以上例子會導(dǎo)致如下輸出,代碼如下:
- NULL
- object(stdClass)(0) {
- }
類似的行為也適用于 static 語句,引用并不是靜態(tài)地存儲的,代碼如下:
- <?php
- function &get_instance_ref() {
- static $obj;
- echo "Static object: ";
- var_dump($obj);
- if (!isset($obj)) {
- // 將一個引用賦值給靜態(tài)變量
- $obj = &new stdclass;
- }
- $obj->property++;
- return $obj;
- }
- function &get_instance_noref() {
- static $obj;
- echo "Static object: ";
- var_dump($obj);
- if (!isset($obj)) {
- // 將一個對象賦值給靜態(tài)變量
- $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();
- ?>
執(zhí)行以上例子會導(dǎo)致如下輸出:
- Static object: NULL
- Static object: NULL
- Static object: NULL
- Static object: object(stdClass)(1) {
- ["property"]=>
- int(1)
- }
上例演示了當(dāng)把一個引用賦值給一個靜態(tài)變量時,第二次調(diào)用 &get_instance_ref() 函數(shù)時其值并沒有被記住.
注:
1.函數(shù)外部聲明靜態(tài)變量意義不大,函數(shù)內(nèi)部聲明靜態(tài)變量受限于作用域,函數(shù)外部不能修改函數(shù)內(nèi)部靜態(tài)變量.
2.引用變量,也是變量,只不過它的值是變量的內(nèi)存地址.
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:
- ?>
函數(shù)外和內(nèi)都有變量$i,但是他們二個是完全不同的變量,函數(shù)外的$i是全局變量,該內(nèi)存空間直到腳本運行結(jié)束后才會被釋放,函數(shù)內(nèi)的$i是局部變量,程序流經(jīng)過函數(shù)的時候,初始化,退出函數(shù)的時候,內(nèi)存被系統(tǒng)回收,再次調(diào)用函數(shù),則再次分配內(nèi)存空間和回收內(nèi)存空間,二次分配的內(nèi)存空間有可能是同一內(nèi)存地址,也有可能不能同一內(nèi)存地址.
與$i不同的是$j,通過關(guān)鍵字global將局部變量”轉(zhuǎn)為”全局變量,當(dāng)調(diào)用函數(shù)global_var()的時候,并不會重新給$j分配內(nèi)存空間,同樣的,可以在函數(shù)外打印$b,卻不能打印$c是因為$b是全局變量,不會被銷毀,而$c則不能打印,$c已經(jīng)不存在了,在退出函數(shù)就給銷毀了,代碼如下:
- <?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
- ?>
首先,我們看函數(shù)外的$b和$c,即是全局變量又是static變量,這里static修飾沒有太大的意義,因為他們都存放在數(shù)據(jù)段(data-segment),直到腳本運行完了之后才會被回收,然后,我們再看函數(shù)里面的$i和$c,函數(shù)調(diào)用后,$i和$c其實都沒有被回收,但是$i輸出是NULL和$c輸出是3,這是因為他們的作用域是函數(shù)內(nèi)部,不是函數(shù)外部,也就是說$i和$c在函數(shù)外是不可見的,函數(shù)內(nèi)static變量的意義就在于此,僅函數(shù)內(nèi)部可見且不會被銷毀,也就是說,保證函退出函數(shù),變量也不會被回收,但又不會被其它函數(shù)修改.(注:函數(shù)外和函數(shù)內(nèi)的$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每調(diào)用一次就累加1,這是因為,局部變量存放在堆段,每次退出函數(shù)時都會被回收,而$i存放在存放在數(shù)據(jù)段(data-segment),直到程序執(zhí)行完畢才會被回收,我們平常說的static變量,如果沒有特別指明,都說的是函數(shù)內(nèi)部的static變量.
引用函數(shù)與static變量
既然static變量要直到腳本執(zhí)行結(jié)束,才會被銷毀,那么,有沒有辦法訪問該變量的值呢?我們來看看下面的示例,代碼如下:
- <?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,這就說明了只要變量沒有被銷毀,還是可以被訪問,我們可以通過引用函數(shù)將static變量的地址返回其它函數(shù),其它函數(shù)則可通過static變量的地址訪問并且修改它的值.
上例第一處??,為什么是8,而不是9,這是因為what_i($ptr)函數(shù),要求參數(shù)是按值傳遞,即此處的$ptr實參值是5,且參數(shù)$ptr和全局變量$ptr是二個不同的變量。第二處??的值是12,為什么不是11的道理亦是如此。what_p(&$ptr)函數(shù),要求參數(shù)是按引用傳遞,即此處的$ptr是指向static變量$i的地址,需要注意的是參數(shù)$ptr和全局變量$ptr也是二個不同的變量,只不過他們都指向同一個地方.
新聞熱點
疑難解答