天天看點

PHP引用與global操作符

普通類型變量的指派與引用

  • 執行個體 1
$a = "ABC" ;  
     $b   =& $a ;
     //此時$b與$a就是同一記憶體的兩個不同名字(表示同一個人),
     //若使用unset($b)則隻是将$b這個變量訓示符(身份證)去掉了,
     //$b所指向的記憶體還可以通路,因為有$a指向它;
     //簡而言之,$a,$b就是一個人身份的證明
     //而“ABC”(value值)就是實際的人
     //unset($a)或unset($b)就是登出身份證明,
     //當一個人所有的身份證明都被登出以後,這個人就不能被通路了。
     //是以引用操作實際就是将身份證明複制一份而已,應該很好了解吧*/
     echo   $a ; // 這裡輸出: ABC  
     echo   $b ; // 這裡輸出: ABC  
     $b = "EFG" ;  
     echo   $a ; // 因為$a與$b指的是同一個人,是以$a的值也變為EFG  
     echo   $b      
  • 執行個體 2
$a   =   1 ;  
     $b   =&   $a ;  
     unset  ( $a );  
     echo $b; // 輸出:1:        

對象的引用(類類型的指派就是引用)

class fooclass{  
    public $att ;   
}  
$a = new fooclass();  
$b = $a;   
$a->att = 1;  
$b->att = 2;  
echo 'a obj:',($a->att),'<br>';  //2
echo 'b obj:',($b->att);  //2      

函數傳參時使用引用

$ b = 2
    funtion change(&$a)//定義方法與c/c++中使用引用的方式類似
    {
        $a = 4;
    }
    change($b);
    echo $b;//ouput:4      

函數傳回引用

function   & test()  
     static   $b = 0 ; // 申明一個靜态變量  
     $b = $b + 1 ;  
     echo   $b ;  
     return   $b ;  
}  
$a = test(); // 這條語句會輸出 $b 的值 為1  
$a = 5 ;  
$a = test(); // 這條語句會輸出 $b 的值 為 2  
$a =& test(); // 這條語句會輸出 $b 的值 為 3  (注意函數的定義以及調用時都要使用&操作符)
$a = 5 ;  
$a = test(); // 這條語句會輸出 $b 的值 為 6      

數組類型變量的指派不是引用

$arr_1 = [1,2,3];
$arr_2 = $arr_1;//在php中array與object是不同的類型,雖然對象的指派就是引用指派(在php5.0以後),數組這裡可以簡單地認為就是新開辟了一塊記憶體(深入來講,其實存在“引用計數、寫時拷貝”的機制)
$arr_2[0] = 2;
foreach ($arr_1 as $value)
{
    echo "value_of_arr1=".$value."<br>";
}

foreach ($arr_2 as $value)
{
    echo "value_of_arr2=".$value."<br>";
}
/*
結果如下:
value_of_arr1=1
value_of_arr1=2
value_of_arr1=3
value_of_arr2=2
value_of_arr2=2
value_of_arr2=3
*/      

結論: PHP 的數組指派是 copy 而非引用,指派過程會建立新的數組賦予被指派的變量。在新變量上的數組操作并不會影響到原數組變量中的内容

引用數組中的元素,引發的” 魔法 “

  • 執行個體 1
$a = array(21, 7);
$c = & $a[0];
$b = $a;
$b[0]= 1;
$b[1]=2;

var_dump($a);
echo '<br/>';
var_dump($b);
echo '<br/>';
var_dump($c);
echo '<br/>';

// Output:
/*  array(2) { [0]=> &int(1) [1]=> int(7) } 
    array(2) { [0]=> &int(1) [1]=> int(2) } 
    string(2) "21"
*/
// 可以看到$a[0]與$b[0]均變為類引用類型;      
  • 執行個體 2(接執行個體 1)
unset($c);
var_dump($a);
echo '<br/>';
var_dump($b);
echo '<br/>';
/* Output:
   array(2) { [0]=> &int(1) [1]=> int(7) } 
   array(2) { [0]=> &int(1) [1]=> int(2) } 
*/
// 此時$a[0]與$b[0]還是類引用類型;      
  • 執行個體 3(接執行個體 2)
unset($a);
var_dump($b);
/* output:
    array(2) { [0]=> &int(1) [1]=> int(7) }
*/
此時$b[0]還是引用類型
接下來就是見證奇迹的時刻啦--見證奇迹的時刻啦----見證奇迹的時刻啦---見證奇迹的時刻啦
但是,如果本執行個體中不是unset($a),而是unset($b),則var_dump($a);
可以看到結果:array(2) { [0]=> int(1) [1]=> int(7) }
也就是說此時$a[0]又變回正常的非引用變量了      

global 操作符

<?php
    $var1 = 1;
    $var2 = 2;
    function test1(){
        $GLOBALS['var2'] = &$GLOBALS['var1'];
        //$GLOBALS['var2']此時就是代表函數外$var1變量本身
    }
    test1();
    echo $var2 . "<br />";

    $var3 = 1;
    $var4 = 2;
    function test2(){
        global $var3;//重點:相當于$var3=& $GLOBALS['var3'];
        global $var4;
        $var4 = &$var3;
    }
    test2();
    echo $var4 . "<br />";
?>      
  • 執行個體 2
$var1 = 1;
function test1(){
    unset($GLOBALS['var1']);
}
test1();
echo $var1 . "<br />";//輸出:Notice: Undefined variable: var1

$var2 = 1;
function test2(){
    global $var2;
    unset($var2);
}
test2();
echo $var2;//輸出1
?>
/*結果:undefined variable 與1
由此可證明global $a;就等價于$a = & $GLOBALS['a'];      

總結

  • 引用操作就是給記憶體取别名(或者說是給一個人多弄一個身份證明)
  • global 操作其實是偷偷使用了引用操作:

    ​​

    ​global $a; 等價于 $a = & $GLOBALS['a']​

  • 要想函數傳回引用,需要都定義函數以及調用函數時,都使用 & 操作符;否則函數傳回的不是引用

牛刀小試

$var1 = "Example variable";  
$var2 = "";  
function global_references($use_globals)  
    global $var1, $var2;  
    if (!$use_globals) {  
        $var2 =& $var1; // $var2隻在該函數内有效
    } else {  
        $GLOBALS["var2"] =& $var1; 
    }  
}  
global_references(false);  
echo "var2 is set to'$var2'", '<br>'; // var2被設定為 ''  
global_references(true);  
echo "var2 is set to'$var2'"; // var2被設定為'Example variable'  //通過該例子可以進一步鞏固我們所學的知識,聰明的你掌握了沒      

繼續閱讀